Clear Environment

# Clear environment of variables and functions
rm(list = ls(all = TRUE)) 
# Clear environmet of packages
if(is.null(sessionInfo()$otherPkgs) == FALSE)lapply(paste("package:", names(sessionInfo()$otherPkgs), sep=""), detach, character.only = TRUE, unload = TRUE)

Load Packages

library(tidyverse)     # For wrangling, subseting, and ploting
library(lubridate)     # For working with dates
library(stringr)        # Used to manipulate strings
library(GGally)        # For ggpairs, a detailed correlation graphic
library(gridExtra)     # For grouping graphs
library(janitor)       # Tidy cross tabs
library(MultinomialCI) # To calculate multinomial confidence intervals  
library(htmlTable)     # To format html tables
library(psych)
library(flexdashboard)
library(here)
library(plotly)
library(kableExtra)
library(scales)
library(cowplot)

Standard EDA Process

  1. Univariate non-graphical
  • categorical (i.e. factor)
    • count, proportion, percentage
  • quantitative
    • central tendancy, dispersion, skewness, kurtosis, etc
  1. Univariate graphical
  • categorical
    • histogram or barplot of factors, pie chart
  • quantitative
    • histogram (try different bin) or density, boxplot, quantile-normal plot
  1. Multi-variate non-graphical
  • categorical
    • cross-tabluation if multiple categorical variables
  • quantitative
    • correlation (and covariance)
  1. Multi-variate graphical
  • categorical
    • tile graph
  • quantitative
    • scatter plot, correlation plot
  • categorical and quantitative
    • distribution or summary of quantitative by level of categorical variable
    • multiple boxplots
    • scatter plot with color, size, or shape by factor or continuous variable

Load and review data

Work with datasets

  • Load and work with seattle_reign
# Load data
seattle_reign <- read.csv("Seattle_Reign.csv")
# Work with a copy of prod_data
seattle_reign_raw_data <- seattle_reign
# Review data structure
#str(seattle_reign)
#summary(seattle_reign)

Filtering required data

# Filtering required variables based on the data dictionary
# factor_1 = attendance
# factor_2 = sales
# factor_3 = media
# factor_4 = merchandise
# factor_5 = demographics
# factor_6 = satisfaction
seattle_reign <- seattle_reign_raw_data %>%
  mutate(
         factor1_attend = as.factor(Attend1),
         att_first_attend = case_when(Attend2 == 2013 ~ "Attended_2013",
                                           Attend2 == 2014 ~ "Attended_2014",
                                           Attend2 == 2015 ~ "Attended_2015",
                                           Attend2 == 2016 ~ "Attended_2016",
                                           TRUE ~ "NotAttended"),
         att_first_attend = as.factor(att_first_attend),
         att_attend_2016 = case_when(Attend3 == "Yes" ~ "1",                                                                                               TRUE ~ "0"),
         att_attend_2016 = as.factor(att_attend_2016),
         att_interest = case_when(str_detect(Interest,"I live and die with this team") ~ "Die_heart_fan",
                              str_detect(Interest,"I consider myself to be a loyal fan of this team") ~ "Loyal_fan",
                              str_detect(Interest,"I consider myself to be a moderate fan of this team") ~ "Moderate_fan",
                              str_detect(Interest,"I consider myself to be a low-level fan of this team") ~ "Low_level_fan",
                              TRUE ~ "Less_interest"), 
         att_interest = as.factor(att_interest),
         att_gamewith = case_when(Gamewit1 == 1 ~ "Family",
                              Gamewit2 == 1 ~ "Friends",
                              Gamewit3 == 1 ~ "Business Associates",
                              Gamewit4 == 1 ~ "I attend games by myself",
                              TRUE ~ "NotApplicable"),
         att_gamewith = as.factor(att_gamewith),
         att_distance = (Travel5),
         att_travel_mode = as.factor(Travel6),
         att_promo_effect = case_when(str_detect(Promo1,"Has no influence on my attendance") ~ "No influence",
                                   str_detect(Promo1,"Has a positive influence on my attendance") ~ "Positive influence",
                                   str_detect(Promo1,"Had a negative influence on my attendance") ~ "Negative influence",
                                   TRUE ~ "Unknown"),
         att_promo_effect = as.factor(att_promo_effect),
         att_player_fan1 = case_when(str_detect(IDplay1,"Agree") ~ "1",
                                      str_detect(IDplay1,"Disagree") ~ "2",
                                      str_detect(IDplay1,"Somewhat disagree") ~ "2",
                                      str_detect(IDplay1,"Somewhat agree") ~ "1",
                                      str_detect(IDplay1,"Strongly agree") ~ "1",
                                      str_detect(IDplay1,"Strongly Disagree") ~ "2",
                                      TRUE ~ "0"),
         
         att_attend_2017_1 = case_when(str_detect(Attend17,"Agree") ~ "1",
                                      str_detect(Attend17,"Disagree") ~ "2",
                                      str_detect(Attend17,"Somewhat disagree") ~ "2",
                                      str_detect(Attend17,"Somewhat agree") ~ "1",
                                      str_detect(Attend17,"Strongly agree") ~ "1",
                                      str_detect(Attend17,"Strongly Disagree") ~ "2",
                                      TRUE ~ "0"),
         att_player_fan = case_when(att_player_fan1 == 1 ~ "Player_Fan",
                                           att_player_fan1 == 2 ~ "Not_a_Player_Fan",
                                           att_player_fan1 == 0 ~ "Neutral"),
         att_attend_2017 = case_when(att_attend_2017_1 == 1 ~ "1",
                                           att_attend_2017_1 == 2 ~ "0",
                                           att_attend_2017_1 == 0 ~ "0"),
         att_player_fan = as.factor(att_player_fan),
         att_attend_2017 = as.factor(att_attend_2017),
         att_most_pref_time = case_when(GameTim1==1 ~ "Wed Evenings",
                                          GameTim1==2 ~ "Friday Evenings",
                                          GameTim1==3 ~ "Saturday Afternoons 1pm",
                                          GameTim1==4 ~ "Saturday Afternoons 4pm",
                                          GameTim1==5 ~ "Saturday Evenings",
                                          GameTim1==6 ~ "Sunday Afternoons 4pm",
                                          GameTim1==7 ~ "Sunday Evenings",
                                          TRUE ~ "NoPreference"),
         att_most_pref_time = as.factor(att_most_pref_time),
         att_least_preferred_timing = case_when(GameTim7==1 ~ "Wed Evenings",
                                          GameTim7==2 ~ "Friday Evenings",
                                          GameTim7==3 ~ "Saturday Afternoons 1pm",
                                          GameTim7==4 ~ "Saturday Afternoons 4pm",
                                          GameTim7==5 ~ "Saturday Evenings",
                                          GameTim7==6 ~ "Sunday Afternoons 4pm",
                                          GameTim7==7 ~ "Sunday Evenings",
                                          TRUE ~ "NoPreference"),
         att_least_preferred_timing = as.factor(att_least_preferred_timing),
         
         sales_ticket_type = as.factor(lasttype),
         sales_numofmatch_2017 = (Gamepln1),
         sales_tkt_type_2017 = case_when(Gampln2a == 1 ~ "Season Ticket",
                              Gampln2b == 1 ~ "5 Match Pack",
                              Gampln2c == 1 ~ "3 Match Pack",
                              Gampln2d == 1 ~ "Single Match",
                              Gampln2e == 1 ~ "Pitchside Table",
                              Gampln2f == 1 ~ "Undecided"),
         sales_tkt_type_2017 = as.factor(sales_tkt_type_2017),
         media_web = case_when(Media8_1 == 1|Media8_2 == 1|Media8_3==1|Media8_4==1|Media8_5==1 ~ "Website",                                          Media8_1 == 2|Media8_2 == 2|Media8_3==2|Media8_4==2|Media8_5==2 ~ "Facebook",
                              Media8_1 == 3|Media8_2 == 3|Media8_3==3|Media8_4==3|Media8_5==3 ~ "Twitter",
                              Media8_1 == 4|Media8_2 == 4|Media8_3==4|Media8_4==4|Media8_5==4 ~ "Instragram",
                              Media8_1 == 5|Media8_2 == 5|Media8_3==5|Media8_4==5|Media8_5==5 ~ "Youtube",
                              TRUE ~ "NotAvailable"),
         media_web = as.factor(media_web),
         media_season_newspaper = (Media9),
         media_season_tv = (Media10),
         media_ads1 = case_when(str_detect(Media1,"Has no influence on my attendance") ~ "No_inf_newspaper",
                                   str_detect(Media1,"Has a positive influence on my attendance") ~ "Newspaper_pos",
                                   str_detect(Media1,"Had a negative influence on my attendance") ~ "Newspaper_neg",
                                   TRUE ~ "Unknown"),
         media_ads3 = case_when(str_detect(Media3,"Has no influence on my attendance") ~ "No_inf_FCBillboard",
                                   str_detect(Media3,"Has a positive influence on my attendance") ~ "FCBillboard_pos",
                                   str_detect(Media3,"Had a negative influence on my attendance") ~ "FCBillboard_neg",
                                   TRUE ~ "Unknown"),
         media_ads4 = case_when(str_detect(Media4,"Has no influence on my attendance") ~ "No_infl_radio",
                                   str_detect(Media4,"Has a positive influence on my attendance") ~ "Radio_positive",
                                   str_detect(Media4,"Had a negative influence on my attendance") ~ "Radio_negative",
                                   TRUE ~ "Unknown"),
         media_ads6 = case_when(str_detect(Media6,"Has no influence on my attendance") ~ "No_infl_internet",
                                   str_detect(Media6,"Has a positive influence on my attendance") ~ "internet_positive",
                                   str_detect(Media6,"Had a negative influence on my attendance") ~ "internet_negative",
                                   TRUE ~ "Unknown"),
         media_ads = case_when(media_ads1 == "Newspaper_pos" ~ "Newspaper_ads",
                                  media_ads3 == "FCBillboard_pos" ~ "FCBillboard_ads",
                                  media_ads4 == "Radio_positive" ~ "Radio_ads",
                                  media_ads6 == "internet_positive" ~ "Internet_ads"
          ),
         media_ads = as.factor(media_ads),
         media_ads1 = as.factor(media_ads1),
         media_ads3 = as.factor(media_ads3),
         media_ads4 = as.factor(media_ads4),
         media_ads6 = as.factor(media_ads6),
         mer_buy_online1 = case_when(str_detect(Buyonl1,"Agree") ~ "1",
                                      str_detect(Buyonl1,"Disagree") ~ "2",
                                      str_detect(Buyonl1,"Somewhat disagree") ~ "2",
                                      str_detect(Buyonl1,"Somewhat agree") ~ "1",
                                      str_detect(Buyonl1,"Strongly agree") ~ "1",
                                      str_detect(Buyonl1,"Strongly Disagree") ~ "2",
                                      TRUE ~ "0"),
         mer_buy_online1 = as.factor(mer_buy_online1),
         mer_buy_match1 = case_when(str_detect(BuyMat1,"Agree") ~ "1",
                                      str_detect(BuyMat1,"Disagree") ~ "2",
                                      str_detect(BuyMat1,"Somewhat disagree") ~ "2",
                                      str_detect(BuyMat1,"Somewhat agree") ~ "1",
                                      str_detect(BuyMat1,"Strongly agree") ~ "1",
                                      str_detect(BuyMat1,"Strongly Disagree") ~ "2",
                                      TRUE ~ "0"),
         mer_buy_match1 = as.factor(mer_buy_match1),
         mer_buy_store1 = case_when(str_detect(BuyStor1,"Agree") ~ "1",
                                      str_detect(BuyStor1,"Disagree") ~ "2",
                                      str_detect(BuyStor1,"Somewhat disagree") ~ "2",
                                      str_detect(BuyStor1,"Somewhat agree") ~ "1",
                                      str_detect(BuyStor1,"Strongly agree") ~ "1",
                                      str_detect(BuyStor1,"Strongly Disagree") ~ "2",
                                      TRUE ~ "0"),
         mer_buy_store1 = as.factor(mer_buy_store1),
         mer_buy_online = case_when(mer_buy_online1 == 1 ~ "Buy_Online",
                                           mer_buy_online1 == 2 ~ "DoNot_Buy_Online",
                                           mer_buy_online1 == 0 ~ "Neutral"),
         mer_buy_match = case_when(mer_buy_match1 == 1 ~ "Buy_atMatch",
                                           mer_buy_match1 == 2 ~ "DoNot_Buy_atMatch",
                                           mer_buy_match1 == 0 ~ "Neutral"),
         mer_buy_store = case_when(mer_buy_store1 == 1 ~ "Buy_atStore",
                                           mer_buy_store1 == 2 ~ "DoNot_Buy_atStore",
                                           mer_buy_store1 == 0 ~ "Neutral"),
         mer_buy_online = as.factor(mer_buy_online),
         mer_buy_match = as.factor(mer_buy_match),
         mer_buy_store = as.factor(mer_buy_store),
         mer_buy_pref = case_when(mer_buy_online == "Buy_Online" ~ "Online",
                                                mer_buy_match == "Buy_atMatch" ~ "During Match",
                                                mer_buy_store == "Buy_atStore" ~ "At Store",
                                                TRUE ~ "Neutral"),
         mer_buy_pref = as.factor(mer_buy_pref),
         mer_purchase_sponsors = case_when(Purchs1 == "Yes" ~ "Carter Subaru",
                              Purchs2 == "Yes" ~ "Microsoft",
                              Purchs3 == "Yes" ~ "Pepsi",
                              Purchs4 == "Yes" ~ "BECU",
                              Purchs9 == "Yes" ~ "Kraken Congee",
                              Purchs10 == "Yes" ~ "Ruffneck Scarves",
                              TRUE ~ "Not sure"),
         mer_purchase_sponsors = as.factor(mer_purchase_sponsors),
         mer_reign = case_when(Shirt1 == 1 ~ "Short_Sleeve_Shirt",                                                                                      Shirt2 == 1 ~ "Long_Sleeve_Shirt",
                              Shirt3 == 1 ~ "Jackets",
                              Shirt4 == 1 ~ "Accessories",
                              TRUE ~ "No preferences"
                              ),
         mer_reign = as.factor(mer_reign),
         dem_gender = as.factor(Gender),
         dem_sexualOrient = as.factor(SexOrient),
         dem_race = as.factor(Race),
         att_seaEvent = case_when(SeaEvnt1 == 1 ~ "Seattle Storm",
                              SeaEvnt2 == 1 ~ "Seattle Seahawks",
                              SeaEvnt3 == 1 ~ "Seattle Sounders",
                              SeaEvnt4 == 1 ~ "Seattle Mariners",
                              SeaEvnt6 == 1 ~ "Sounders Women",
                              SeaEvnt7 == 1 ~ "Seattle Majestics",
                              SeaEvnt8 == 1 ~ "Tacoma Stars",
                              SeaEvnt9 == 1 ~ "Rat City Rollergirls",
                              TRUE ~ "NoAnswer"),
         att_seaEvent = as.factor(att_seaEvent),
         dem_marital_status = (Marital),
         dem_education = (Educat),
         sat_price_food = case_when(str_detect(Consat4,"Very Satisfied") ~ "S",
                                      str_detect(Consat4,"Very Dissatisfied") ~ "D",
                                      TRUE ~ "N"),
         sat_quality = case_when(str_detect(Consat1,"Very Satisfied") ~ "S",
                                      str_detect(Consat1,"Very Dissatisfied") ~ "D",
                                      TRUE ~ "N"),
         sat_variety = case_when(str_detect(Consat2,"Very Satisfied") ~ "S",
                                      str_detect(Consat2,"Very Dissatisfied") ~ "D",
                                      TRUE ~ "N"),
         sat_price_drink = case_when(str_detect(Consat5,"Very Satisfied") ~ "S",
                                      str_detect(Consat5,"Very Dissatisfied") ~ "D",
                                      TRUE ~ "N"),
         sat_beer = case_when(str_detect(Beersat1,"Very Satisfied") ~ "S",
                                      str_detect(Beersat1,"Very Dissatisfied") ~ "D",
                                      TRUE ~ "N"),
         sat_gameday = case_when(sat_price_food == "S" ~ "Satisfactory food price",
                                      sat_quality == "S" ~ "Satisfactory quality",
                                      sat_price_drink == "S" ~ "Satisfactory drink price",
                                      sat_variety == "S" ~ "Satisfied with variety",
                                      sat_beer == "S" ~ "Satisfactory beer service",
                                      sat_price_food == "D" ~ "Dissatisfying food price",
                                      sat_quality == "D" ~ "Dissatisfying quality",
                                      sat_price_drink == "D" ~ "Dissatisfying drink price",
                                      sat_variety == "D" ~ "Dissatisfied with variety",
                                      sat_beer == "D" ~ "Dissatisfying beer service",
                              TRUE ~ "Neutral"),
         cost1 = case_when(str_detect(Cost3,"Agree") ~ "A",
                                      str_detect(Cost3,"Disagree") ~ "D",
                                      str_detect(Cost3,"Somewhat disagree") ~ "D",
                                      str_detect(Cost3,"Somewhat agree") ~ "A",
                                      str_detect(Cost3,"Strongly agree") ~ "A",
                                      str_detect(Cost3,"Strongly Disagree") ~ "D",
                                      TRUE ~ "N"),
         cost = if_else(cost1 == "A", "Costly", "Not Costly"),
         cost = as.factor(cost),
         sat_gameday = as.factor(sat_gameday),
         sat_skill = case_when(str_detect(Skill2,"Agree") ~ "A",
                                      str_detect(Skill2,"Disagree") ~ "D",
                                      str_detect(Skill2,"Somewhat disagree") ~ "D",
                                      str_detect(Skill2,"Somewhat agree") ~ "A",
                                      str_detect(Skill2,"Strongly agree") ~ "A",
                                      str_detect(Skill2,"Strongly Disagree") ~ "D",
                                      TRUE ~ "N"), 
          sat_success = case_when(str_detect(Success2,"Agree") ~ "A",
                                      str_detect(Success2,"Disagree") ~ "D",
                                      str_detect(Success2,"Somewhat disagree") ~ "D",
                                      str_detect(Success2,"Somewhat agree") ~ "A",
                                      str_detect(Success2,"Strongly agree") ~ "A",
                                      str_detect(Success2,"Strongly Disagree") ~ "D",
                                      TRUE ~ "N"), 
          sat_drama = case_when(str_detect(Drama4,"Agree") ~ "A",
                                      str_detect(Drama4,"Disagree") ~ "D",
                                      str_detect(Drama4,"Somewhat disagree") ~ "D",
                                      str_detect(Drama4,"Somewhat agree") ~ "A",
                                      str_detect(Drama4,"Strongly agree") ~ "A",
                                      str_detect(Drama4,"Strongly Disagree") ~ "D",
                                      TRUE ~ "N"),
          sat_cost = case_when(str_detect(Cost3,"Agree") ~ "A",
                                      str_detect(Cost3,"Disagree") ~ "D",
                                      str_detect(Cost3,"Somewhat disagree") ~ "D",
                                      str_detect(Cost3,"Somewhat agree") ~ "A",
                                      str_detect(Cost3,"Strongly agree") ~ "A",
                                      str_detect(Cost3,"Strongly Disagree") ~ "D",
                                      TRUE ~ "N"),
          satisfacn_perf = case_when(sat_skill == "A" ~ "Satisfied_with_skill",
                                      sat_success == "A" ~ "Satisfied_with_success",
                                      sat_drama == "A" ~ "Satisfied_with_drama",
                                      sat_cost == "A" ~ "Satisfied_with_cost",
                                      sat_skill == "D" ~ "Not Satisfied_skill",
                                      sat_success == "D" ~ "TNot Satisfied_success",
                                      sat_drama == "D" ~ "Not Satisfied_drama",
                                      sat_cost == "D" ~ "Not Satisfied_cost",
                              TRUE ~ "Not Satisfied"),
          satisfacn_perf = as.factor(satisfacn_perf)
          
  
           ) %>%
  filter(att_distance != "NA") %>%
  filter(sales_numofmatch_2017 != "NA")  %>% 
  filter(media_season_tv != "NA") %>%
  filter(media_season_newspaper != "NA") %>%
  #filter(media_ads!= "NA")  %>%
  filter(SpndlstS != "NA") %>%
  filter(SpndlstO != "NA") %>%
  rename(sales_exp_self2016 = SpndlstS, 
         sales_exp_oth2016 = SpndlstO) %>%
  select(factor1_attend,att_first_attend,att_interest,att_gamewith,att_travel_mode,att_distance,
         att_promo_effect,att_player_fan,att_seaEvent, att_most_pref_time,
         att_least_preferred_timing,att_attend_2017,att_attend_2016, att_gamewith,
         sales_ticket_type, sales_exp_self2016, 
         sales_exp_oth2016,sales_numofmatch_2017,sales_tkt_type_2017,media_web,
         media_season_newspaper,media_season_tv,
         mer_buy_pref,cost,
         mer_purchase_sponsors,mer_reign,dem_gender,dem_sexualOrient,dem_marital_status,
         dem_education,sat_gameday,satisfacn_perf)  %>%
  drop_na()
#Examine the first 10 observations to make sure data set looks ok
#head(seattle_reign,10)
# Descriptive statistics
#summary(seattle_reign)
# Review data structures
#str(seattle_reign)
# The palette with grey:
cbPalette <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
Observations
  • Data for the Seattle Reign FC Soccer Team
  • 416 observations of 23 variables
  • 17 Factor Variables
  • 5 Integer Variable
  • 1 Numeric Variables

Selecting relevant columns

# Select required columns from raw data
sea_reign_data <- seattle_reign %>%
   select(att_first_attend,att_interest,att_distance,
         att_promo_effect,att_seaEvent, att_most_pref_time,
         att_attend_2017,att_attend_2016,att_gamewith,
         sales_ticket_type, sales_exp_self2016, 
         sales_exp_oth2016,sales_numofmatch_2017,sales_tkt_type_2017,
         media_web,cost,
         media_season_newspaper,media_season_tv,
         mer_buy_pref,
         mer_purchase_sponsors,mer_reign,dem_gender,dem_sexualOrient,dem_marital_status,
         dem_education,sat_gameday,satisfacn_perf)
summary(sea_reign_data)
      att_first_attend        att_interest  att_distance            att_promo_effect               att_seaEvent
 Attended_2013:109     Die_heart_fan: 29   Min.   : 0.0   Negative influence:  1     NoAnswer            : 56  
 Attended_2014:113     Less_interest:  1   1st Qu.: 5.0   No influence      : 85     Rat City Rollergirls:  4  
 Attended_2015:123     Low_level_fan: 25   Median :10.0   Positive influence:162     Seattle Mariners    : 27  
 Attended_2016: 69     Loyal_fan    :241   Mean   :15.8   Unknown           :166     Seattle Seahawks    : 59  
 NotAttended  :  0     Moderate_fan :118   3rd Qu.:20.0                              Seattle Sounders    :159  
                                           Max.   :80.0                              Seattle Storm       :108  
                                                                                     Sounders Women      :  1  
               att_most_pref_time att_attend_2017 att_attend_2016                   att_gamewith       sales_ticket_type
 Sunday Evenings        :248      0: 41           0: 58           Family                  :306   3 Match Pack   :  5    
 Sunday Afternoons 4pm  : 54      1:373           1:356           Friends                 : 90   5 Match Pack   : 17    
 NoPreference           : 35                                      I attend games by myself: 18   I don't know   : 26    
 Saturday Afternoons 4pm: 21                                      NotApplicable           :  0   Pitchside Table:  2    
 Wed Evenings           : 21                                                                     Season Ticket  :134    
 Saturday Evenings      : 17                                                                     Single Match   :230    
 (Other)                : 18                                                                                            
 sales_exp_self2016 sales_exp_oth2016 sales_numofmatch_2017      sales_tkt_type_2017        media_web           cost    
 Min.   :  0.00     Min.   :  0.00    Min.   : 0.000        3 Match Pack   : 21      Facebook    : 47   Costly    :344  
 1st Qu.:  0.00     1st Qu.:  0.00    1st Qu.: 2.000        5 Match Pack   : 30      Instragram  :  5   Not Costly: 70  
 Median : 25.00     Median : 20.00    Median : 5.000        Pitchside Table:  4      NotAvailable: 56                   
 Mean   : 43.56     Mean   : 39.47    Mean   : 5.804        Season Ticket  :134      Twitter     : 16                   
 3rd Qu.: 60.00     3rd Qu.: 60.00    3rd Qu.:10.000        Single Match   :186      Website     :275                   
 Max.   :250.00     Max.   :200.00    Max.   :16.000        Undecided      : 39      Youtube     : 15                   
                                                                                                                        
 media_season_newspaper media_season_tv        mer_buy_pref      mer_purchase_sponsors              mer_reign  
 Min.   :0.000          Min.   : 0.000   At Store    : 26   BECU            : 45       Accessories       : 22  
 1st Qu.:0.000          1st Qu.: 0.000   During Match:116   Carter Subaru   : 20       Jackets           : 16  
 Median :1.000          Median : 1.000   Neutral     :130   Kraken Congee   :  8       Long_Sleeve_Shirt : 47  
 Mean   :1.401          Mean   : 1.874   Online      :142   Microsoft       :154       No preferences    : 73  
 3rd Qu.:2.000          3rd Qu.: 3.000                      Not sure        : 97       Short_Sleeve_Shirt:256  
 Max.   :5.000          Max.   :10.000                      Pepsi           : 80                               
                                                            Ruffneck Scarves: 10                               
                dem_gender              dem_sexualOrient         dem_marital_status              dem_education
 Female              :252   Bisexual            : 20     Married/Partnered:286      College Graduate    :182  
 Male                :157   Gay/Lesbian         : 76     Other            :  3      Graduate Degree     :177  
 Prefer not to answer:  5   Heterosexual        :297     Single           :125      High School Graduate:  7  
                            Other               :  8                                Other               :  2  
                            Prefer not to answer: 13                                Some College        : 46  
                                                                                                              
                                                                                                              
                     sat_gameday                 satisfacn_perf
 Neutral                   :325   Not Satisfied         :  0   
 Dissatisfying beer service: 25   Not Satisfied_skill   :  2   
 Satisfactory food price   : 22   Satisfied_with_cost   :  3   
 Satisfactory quality      : 13   Satisfied_with_drama  :  6   
 Satisfactory beer service :  7   Satisfied_with_skill  :393   
 Dissatisfying food price  :  6   Satisfied_with_success: 10   
 (Other)                   : 16                                

Ask questions to follow up on in detailed EDA
1. How do the attendance vary when people travelled longer distance to watch the match?
2. How do the attendance vary when people attended a previous match and when they have not?
3. How does media such as website, facebook effect the number of people who are likely to attend a match in 2017? 4. What is the purchasing habits of people who have attended previous matches? 5. How is the overall game day experience of people who have attended the matches in past? 6. What is the impact of sponsors in selling the merchandise at store vs online vs during match?

# Selecting relevant columns for flexdashboard
sea_flexdash <- sea_reign_data %>%
   select(att_promo_effect, att_most_pref_time,sales_exp_self2016, att_attend_2016,
         sales_exp_oth2016,sales_numofmatch_2017,sales_tkt_type_2017,mer_buy_pref,
         att_attend_2017, mer_reign,dem_gender,dem_education)
write.csv(sea_flexdash, "/Users/LoveHonu/Documents/Winter2019/BUAN5210-Visualization/sea_flexdash.csv")
 
summary(sea_flexdash)
           att_promo_effect               att_most_pref_time sales_exp_self2016 att_attend_2016 sales_exp_oth2016
 Negative influence:  1     Sunday Evenings        :248      Min.   :  0.00     0: 58           Min.   :  0.00   
 No influence      : 85     Sunday Afternoons 4pm  : 54      1st Qu.:  0.00     1:356           1st Qu.:  0.00   
 Positive influence:162     NoPreference           : 35      Median : 25.00                     Median : 20.00   
 Unknown           :166     Saturday Afternoons 4pm: 21      Mean   : 43.56                     Mean   : 39.47   
                            Wed Evenings           : 21      3rd Qu.: 60.00                     3rd Qu.: 60.00   
                            Saturday Evenings      : 17      Max.   :250.00                     Max.   :200.00   
                            (Other)                : 18                                                          
 sales_numofmatch_2017      sales_tkt_type_2017       mer_buy_pref att_attend_2017              mer_reign  
 Min.   : 0.000        3 Match Pack   : 21      At Store    : 26   0: 41           Accessories       : 22  
 1st Qu.: 2.000        5 Match Pack   : 30      During Match:116   1:373           Jackets           : 16  
 Median : 5.000        Pitchside Table:  4      Neutral     :130                   Long_Sleeve_Shirt : 47  
 Mean   : 5.804        Season Ticket  :134      Online      :142                   No preferences    : 73  
 3rd Qu.:10.000        Single Match   :186                                         Short_Sleeve_Shirt:256  
 Max.   :16.000        Undecided      : 39                                                                 
                                                                                                           
                dem_gender               dem_education
 Female              :252   College Graduate    :182  
 Male                :157   Graduate Degree     :177  
 Prefer not to answer:  5   High School Graduate:  7  
                            Other               :  2  
                            Some College        : 46  
                                                      
                                                      

1. Univariate non-graphical - Categorical

  • Categorical data - tabulation

Factor1 Attendance

Attendance_Past_Years

# group_by() flavor
attendance_first <- sea_reign_data %>%  # %>% Pipes data to group_by() function
  group_by(att_first_attend) %>%           # group_by() organises data by region
  summarise(count = n(),                        # count is the new variable name, n() is a counting function
      percent = (sum(count) / nrow(sea_reign_data)) * 100, # percent is a new variable, sum() and nrow() are functions
      avg_distance = mean(att_distance))             # mean distance travelled
attendance_first
  • 2013 attendance is highest

Attendance_Interest

attendance_interest <- sea_reign_data %>% 
  group_by(att_interest) %>%         
  summarise(count = n(),        
                               
      percent = (sum(count) / nrow(sea_reign_data)) * 100, # percent is a new variable, sum() and nrow() are functions
      avg_distance = mean(att_distance))                        # mean distance travelled
attendance_interest

Attendance_Local_Event

# group_by() brand name
attendance_local_event <- sea_reign_data %>% 
  group_by(att_seaEvent) %>%           # group_by() organises data by producer
  summarise(count = n(),       
      percent = (sum(count) / nrow(sea_reign_data)) * 100, # percent is a new variable, sum() and nrow() are functions
      avg_distance = mean(att_distance))                        # mean distance travelled
attendance_local_event

Attendance_Promo_Effect

# group_by() ad
attendance_promo_effect <- sea_reign_data %>% 
  group_by(att_promo_effect) %>%           # group_by() organises data by producer
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, # percent is a new variable, sum() and nrow() are functions
      avg_distance = mean(att_distance))                        # mean distance travelled
attendance_promo_effect

Attendance_2017

# group_by() ad
attendance_2017 <- sea_reign_data %>% 
  group_by(att_attend_2017) %>%           
  summarise(count = n(),      
      percent = (sum(count) / nrow(sea_reign_data)) * 100,
      avg_distance = mean(att_distance))                      
attendance_2017

Attendance_Pref_Timing

# group_by() ad
attendance_timing <- sea_reign_data %>%  
  group_by(att_most_pref_time) %>%          
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
      avg_distance = mean(att_distance))                       
attendance_timing

Factor2-Sales

Sales_Ticket_Type

sales_ticket_type <- sea_reign_data %>%  
  group_by(sales_ticket_type) %>%           # group_by() organises data 
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
       avg_exp_self = mean(sales_exp_self2016),                        # mean distance travelled
       avg_exp_others = mean(sales_exp_oth2016))                        # mean distance travelled
      # count_match_2016 = sum(att_first_attend_2016))                        # mean distance travelled
sales_ticket_type
sales_ticket_type_2017 <- sea_reign_data %>%  
  group_by(sales_tkt_type_2017) %>%           # group_by() organises data by ticket type
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
       avg_exp_self = mean(sales_exp_self2016),                     
       avg_exp_others = mean(sales_exp_oth2016),    # mean expenditure
       numberofmatch_2017 = sum(sales_numofmatch_2017))   # mean of num of matches
sales_ticket_type_2017

Media_Web

media_web <- sea_reign_data %>%  
  group_by(media_web) %>%           # group_by() organises data by web media used
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
       numberofmatch_2017 = sum(sales_numofmatch_2017))                        # mean of num of matches
media_web

Merchandise_Purchase_Sponsors

merchandise_sponsors <- sea_reign_data %>%  
  group_by(mer_purchase_sponsors) %>%           # group_by() organises data by web media used
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
       numberofmatch_2017 = sum(sales_numofmatch_2017))                        # mean of num of matches
merchandise_sponsors

Merchandise_ReignFC

merchandise_reign <- sea_reign_data %>%  
  group_by(mer_reign) %>%           # group_by() organises data by web media used
  summarise(count = n(),        
      percent = (sum(count) / nrow(sea_reign_data)) * 100, 
       numberofmatch_2017 = sum(sales_numofmatch_2017))                        # mean of num of matches
merchandise_reign

2. Univariate graphical - Categorical

Attendance past years Seattle FC Reign match

# Code histograms using grid.arrange to see quant variables together group by when first attended a Seattle Reign FC match
grid.arrange(
  
  sea_reign_data %>% 
    ggplot(aes(x = att_first_attend, y = att_distance)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_first_attend, y = media_season_newspaper)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_first_attend, y = media_season_tv)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_first_attend, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • People who first attended a Seattle Reign FC match, travelled maximum distance of 2000 miles in 2015, declined in 2016
  • In 2013, approximately 180 times per week during the season people read about the Reign in the newspaper who attended match
  • In 2015, approximately 280 times during the season people watch the Reign on TV who attended match, only 60 times in 2016
  • People who have attended a 2016 match, are least likely to attend a match in 2017

Attendance local event

# Code histograms using grid.arrange so can see all quant variables together group by local events attendance
grid.arrange(
  
  sea_reign_data %>% 
    ggplot(aes(x = att_seaEvent, y = att_distance)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_seaEvent, y = media_season_newspaper)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_seaEvent, y = media_season_tv)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_seaEvent, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • People who follow Seattle Sounders, are more likely to attend the Seattle Reign FC match in 2017

Attendance preferred timings

# Code histograms using grid.arrange so can see all quant variables together group by most preferred timings
grid.arrange(
  
  sea_reign_data %>% 
    ggplot(aes(x = att_most_pref_time, y = att_distance)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = att_most_pref_time, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • People who are likely to attend matches in 2017 prefer a game on Sunday Evenings

Attendance Ticket Type

# Code histograms using grid.arrange so can see all quant variables together group by ticket type
grid.arrange(
  sea_reign_data %>% 
    ggplot(aes(x = sales_ticket_type, y = att_distance)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = sales_ticket_type, y = media_season_newspaper)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = sales_ticket_type, y = media_season_tv)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = sales_ticket_type, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • People who are travelling maximum distances are more likely to buy single match tickets
  • People who are more likely to attend Season 2017, prefer to buy Season Ticket

Media advertisements

# Code histograms using grid.arrange so can see all quant variables together group by advertisements
grid.arrange(
  sea_reign_data %>% 
    ggplot(aes(x = media_web, y = att_distance)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = media_web, y = media_season_newspaper)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = media_web, y = media_season_tv)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = media_web, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • Clearly, website is the most popular media, facebook is second

Merchandise Buying Preferences

# Code histograms using grid.arrange so can see all quant variables together group by buying preferences
grid.arrange(
  sea_reign_data %>% 
    ggplot(aes(x = mer_buy_pref, y = sales_exp_self2016)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  sea_reign_data %>% 
    ggplot(aes(x = mer_buy_pref, y = sales_exp_oth2016)) +
      geom_bar(stat = "identity") +
      coord_flip(),
    sea_reign_data %>% 
    ggplot(aes(x = mer_buy_pref, y = sales_numofmatch_2017)) +
      geom_bar(stat = "identity") +
      coord_flip(),
  ncol = 2
)

  • In the year 2016, most people spend on self and others by Online merchandise purchases
  • Second preference was expenditure during the match
  • People who are likely to attend the match in 2017, have a buying preference of Online as maximum

3. Univariate non-graphical – Quantitative

# Descriptive statistics
summary(sea_reign_data)
      att_first_attend        att_interest  att_distance            att_promo_effect               att_seaEvent
 Attended_2013:109     Die_heart_fan: 29   Min.   : 0.0   Negative influence:  1     NoAnswer            : 56  
 Attended_2014:113     Less_interest:  1   1st Qu.: 5.0   No influence      : 85     Rat City Rollergirls:  4  
 Attended_2015:123     Low_level_fan: 25   Median :10.0   Positive influence:162     Seattle Mariners    : 27  
 Attended_2016: 69     Loyal_fan    :241   Mean   :15.8   Unknown           :166     Seattle Seahawks    : 59  
 NotAttended  :  0     Moderate_fan :118   3rd Qu.:20.0                              Seattle Sounders    :159  
                                           Max.   :80.0                              Seattle Storm       :108  
                                                                                     Sounders Women      :  1  
               att_most_pref_time att_attend_2017 att_attend_2016                   att_gamewith       sales_ticket_type
 Sunday Evenings        :248      0: 41           0: 58           Family                  :306   3 Match Pack   :  5    
 Sunday Afternoons 4pm  : 54      1:373           1:356           Friends                 : 90   5 Match Pack   : 17    
 NoPreference           : 35                                      I attend games by myself: 18   I don't know   : 26    
 Saturday Afternoons 4pm: 21                                      NotApplicable           :  0   Pitchside Table:  2    
 Wed Evenings           : 21                                                                     Season Ticket  :134    
 Saturday Evenings      : 17                                                                     Single Match   :230    
 (Other)                : 18                                                                                            
 sales_exp_self2016 sales_exp_oth2016 sales_numofmatch_2017      sales_tkt_type_2017        media_web           cost    
 Min.   :  0.00     Min.   :  0.00    Min.   : 0.000        3 Match Pack   : 21      Facebook    : 47   Costly    :344  
 1st Qu.:  0.00     1st Qu.:  0.00    1st Qu.: 2.000        5 Match Pack   : 30      Instragram  :  5   Not Costly: 70  
 Median : 25.00     Median : 20.00    Median : 5.000        Pitchside Table:  4      NotAvailable: 56                   
 Mean   : 43.56     Mean   : 39.47    Mean   : 5.804        Season Ticket  :134      Twitter     : 16                   
 3rd Qu.: 60.00     3rd Qu.: 60.00    3rd Qu.:10.000        Single Match   :186      Website     :275                   
 Max.   :250.00     Max.   :200.00    Max.   :16.000        Undecided      : 39      Youtube     : 15                   
                                                                                                                        
 media_season_newspaper media_season_tv        mer_buy_pref      mer_purchase_sponsors              mer_reign  
 Min.   :0.000          Min.   : 0.000   At Store    : 26   BECU            : 45       Accessories       : 22  
 1st Qu.:0.000          1st Qu.: 0.000   During Match:116   Carter Subaru   : 20       Jackets           : 16  
 Median :1.000          Median : 1.000   Neutral     :130   Kraken Congee   :  8       Long_Sleeve_Shirt : 47  
 Mean   :1.401          Mean   : 1.874   Online      :142   Microsoft       :154       No preferences    : 73  
 3rd Qu.:2.000          3rd Qu.: 3.000                      Not sure        : 97       Short_Sleeve_Shirt:256  
 Max.   :5.000          Max.   :10.000                      Pepsi           : 80                               
                                                            Ruffneck Scarves: 10                               
                dem_gender              dem_sexualOrient         dem_marital_status              dem_education
 Female              :252   Bisexual            : 20     Married/Partnered:286      College Graduate    :182  
 Male                :157   Gay/Lesbian         : 76     Other            :  3      Graduate Degree     :177  
 Prefer not to answer:  5   Heterosexual        :297     Single           :125      High School Graduate:  7  
                            Other               :  8                                Other               :  2  
                            Prefer not to answer: 13                                Some College        : 46  
                                                                                                              
                                                                                                              
                     sat_gameday                 satisfacn_perf
 Neutral                   :325   Not Satisfied         :  0   
 Dissatisfying beer service: 25   Not Satisfied_skill   :  2   
 Satisfactory food price   : 22   Satisfied_with_cost   :  3   
 Satisfactory quality      : 13   Satisfied_with_drama  :  6   
 Satisfactory beer service :  7   Satisfied_with_skill  :393   
 Dissatisfying food price  :  6   Satisfied_with_success: 10   
 (Other)                   : 16                                

4. Univariate graphical - Quantitative

Histograms

# Code histograms using grid.arrange so can see all quant variables together
grid.arrange(
  sea_reign_data %>% 
    ggplot(aes(att_distance)) +
      geom_histogram(),
  sea_reign_data %>% 
    ggplot(aes(sales_numofmatch_2017)) +
      geom_histogram(),
  sea_reign_data %>% 
    ggplot(aes(sales_exp_self2016)) +
      geom_histogram(),
  sea_reign_data %>% 
    ggplot(aes(sales_exp_oth2016)) +
      geom_histogram(),
  
  ncol = 2
)

  • Maximum count is for least distance travelled people who are attending the match
  • Maximum count is 0 for expenditure for self, very few have higher expenses

Boxplots

# Set grid pattern for graph arrangement
par(mfrow = c(2, 2))
boxplot(sea_reign_data$att_distance, main = "Attendance_distance_travelled")
boxplot(sea_reign_data$sales_numofmatch_2017, main = "Sales_NumberOfMatches")
boxplot(sea_reign_data$sales_exp_self2016, main = "Sales_Expenditure_Self2016")
boxplot(sea_reign_data$sales_exp_oth2016, main = "Sales_Expenditure_Others2016")

5. Multivariate non-graphical - Categorical

Crosstabs

Cross-tabs are used for tabulation of categorical variables

addmargins(xtabs(~ att_first_attend + att_interest, data = sea_reign_data))
                att_interest
att_first_attend Die_heart_fan Less_interest Low_level_fan Loyal_fan Moderate_fan Sum
   Attended_2013            15             0             2        72           20 109
   Attended_2014             7             1             6        64           35 113
   Attended_2015             6             0             7        73           37 123
   Attended_2016             1             0            10        32           26  69
   NotAttended               0             0             0         0            0   0
   Sum                      29             1            25       241          118 414
addmargins(xtabs(~ att_first_attend + att_promo_effect, data = sea_reign_data))
                att_promo_effect
att_first_attend Negative influence No influence Positive influence Unknown Sum
   Attended_2013                  0           21                 41      47 109
   Attended_2014                  1           22                 43      47 113
   Attended_2015                  0           24                 50      49 123
   Attended_2016                  0           18                 28      23  69
   NotAttended                    0            0                  0       0   0
   Sum                            1           85                162     166 414
addmargins(xtabs(~ att_first_attend + att_most_pref_time,  data = sea_reign_data))
                att_most_pref_time
att_first_attend Friday Evenings NoPreference Saturday Afternoons 1pm Saturday Afternoons 4pm Saturday Evenings
   Attended_2013               1           10                       6                      10                 7
   Attended_2014               1            8                       2                       5                 4
   Attended_2015               5           13                       1                       5                 2
   Attended_2016               1            4                       1                       1                 4
   NotAttended                 0            0                       0                       0                 0
   Sum                         8           35                      10                      21                17
                att_most_pref_time
att_first_attend Sunday Afternoons 4pm Sunday Evenings Wed Evenings Sum
   Attended_2013                    19              49            7 109
   Attended_2014                    15              73            5 113
   Attended_2015                    13              81            3 123
   Attended_2016                     7              45            6  69
   NotAttended                       0               0            0   0
   Sum                              54             248           21 414
addmargins(xtabs(~ sales_numofmatch_2017 + media_web,  data = sea_reign_data))
                     media_web
sales_numofmatch_2017 Facebook Instragram NotAvailable Twitter Website Youtube Sum
                  0          0          0            6       0       7       3  16
                  1          3          0           11       1      11       1  27
                  2         12          0           10       2      38       1  63
                  3          4          1            9       3      49       2  68
                  4          2          0            4       1      19       1  27
                  5          8          1            6       1      34       4  54
                  6          3          1            1       0      11       0  16
                  7          0          0            0       0       3       0   3
                  8          1          0            1       1      15       0  18
                  9          0          0            2       0       2       0   4
                  10         4          0            1       2      21       1  29
                  11         0          0            0       0       2       0   2
                  12         9          2            5       5      58       2  81
                  14         0          0            0       0       4       0   4
                  15         0          0            0       0       1       0   1
                  16         1          0            0       0       0       0   1
                  Sum       47          5           56      16     275      15 414
addmargins(xtabs(~ sales_numofmatch_2017 + mer_buy_pref,  data = sea_reign_data))
                     mer_buy_pref
sales_numofmatch_2017 At Store During Match Neutral Online Sum
                  0          0            1       7      8  16
                  1          3            6       9      9  27
                  2          2           14      23     24  63
                  3          5           16      24     23  68
                  4          1           11       8      7  27
                  5          3           18      14     19  54
                  6          1            8       3      4  16
                  7          0            3       0      0   3
                  8          0            6       5      7  18
                  9          0            1       2      1   4
                  10         1           10       5     13  29
                  11         0            1       1      0   2
                  12        10           19      27     25  81
                  14         0            1       2      1   4
                  15         0            1       0      0   1
                  16         0            0       0      1   1
                  Sum       26          116     130    142 414
addmargins(xtabs(~ sales_numofmatch_2017 + mer_purchase_sponsors,  data = sea_reign_data))
                     mer_purchase_sponsors
sales_numofmatch_2017 BECU Carter Subaru Kraken Congee Microsoft Not sure Pepsi Ruffneck Scarves Sum
                  0      0             1             0         4        9     2                0  16
                  1      0             1             1         8        9     7                1  27
                  2      5             1             1        27       19    10                0  63
                  3      6             4             0        21       20    13                4  68
                  4      4             0             0        11        5     6                1  27
                  5      6             3             0        24       11     9                1  54
                  6      2             2             0         5        3     4                0  16
                  7      1             0             0         1        0     1                0   3
                  8      1             1             0         7        2     6                1  18
                  9      1             0             0         2        1     0                0   4
                  10     2             2             2         9        6     8                0  29
                  11     1             0             1         0        0     0                0   2
                  12    14             5             3        31       12    14                2  81
                  14     1             0             0         3        0     0                0   4
                  15     1             0             0         0        0     0                0   1
                  16     0             0             0         1        0     0                0   1
                  Sum   45            20             8       154       97    80               10 414
addmargins(xtabs(~ sales_numofmatch_2017 + dem_gender,  data = sea_reign_data))
                     dem_gender
sales_numofmatch_2017 Female Male Prefer not to answer Sum
                  0        8    8                    0  16
                  1       15   12                    0  27
                  2       30   33                    0  63
                  3       42   25                    1  68
                  4       19    8                    0  27
                  5       26   27                    1  54
                  6       13    3                    0  16
                  7        3    0                    0   3
                  8       11    7                    0  18
                  9        2    2                    0   4
                  10      20    8                    1  29
                  11       2    0                    0   2
                  12      57   22                    2  81
                  14       2    2                    0   4
                  15       1    0                    0   1
                  16       1    0                    0   1
                  Sum    252  157                    5 414
addmargins(xtabs(~ sales_numofmatch_2017 + dem_marital_status,  data = sea_reign_data))
                     dem_marital_status
sales_numofmatch_2017 Married/Partnered Other Single Sum
                  0                  11     0      5  16
                  1                  22     0      5  27
                  2                  49     0     14  63
                  3                  53     0     15  68
                  4                  19     0      8  27
                  5                  34     1     19  54
                  6                   9     0      7  16
                  7                   2     0      1   3
                  8                  11     0      7  18
                  9                   3     0      1   4
                  10                 19     1      9  29
                  11                  1     0      1   2
                  12                 49     1     31  81
                  14                  2     0      2   4
                  15                  1     0      0   1
                  16                  1     0      0   1
                  Sum               286     3    125 414
addmargins(xtabs(~ sales_numofmatch_2017 + dem_education,  data = sea_reign_data))
                     dem_education
sales_numofmatch_2017 College Graduate Graduate Degree High School Graduate Other Some College Sum
                  0                 10               6                    0     0            0  16
                  1                  7              15                    0     0            5  27
                  2                 19              32                    2     0           10  63
                  3                 27              32                    1     1            7  68
                  4                 10              14                    0     0            3  27
                  5                 25              18                    4     1            6  54
                  6                  8               8                    0     0            0  16
                  7                  3               0                    0     0            0   3
                  8                 11               6                    0     0            1  18
                  9                  0               4                    0     0            0   4
                  10                11              13                    0     0            5  29
                  11                 1               1                    0     0            0   2
                  12                46              26                    0     0            9  81
                  14                 2               2                    0     0            0   4
                  15                 1               0                    0     0            0   1
                  16                 1               0                    0     0            0   1
                  Sum              182             177                    7     2           46 414
Observations
  • With 249 people attending match, Sunday evenings is most favorite, attendance decreased from 82 to 45 in 2016
  • People who are likely to attend 2017 match, following Seattle FC Reign on website
  • Maximum people who are likely to attend a 2017 match prefer to purchase Online
  • Most popular sponsor among people likely to attend a 2017 match prefer Microsoft as a sponsor
  • Most popular merchandise among people likely to attend a 2017 match is short sleeve shirt
  • Female fans and married people are more in numbers than male fans and single who are going to attend a 2017 match
  • Someone with a bachelor or graduate degree are interested in watching 2017 match

Proportion Cross Tab

# Proportions might be more informative
addmargins(round(prop.table(xtabs(~ att_first_attend + att_interest,  data = sea_reign_data)), 3))
                att_interest
att_first_attend Die_heart_fan Less_interest Low_level_fan Loyal_fan Moderate_fan   Sum
   Attended_2013         0.036         0.000         0.005     0.174        0.048 0.263
   Attended_2014         0.017         0.002         0.014     0.155        0.085 0.273
   Attended_2015         0.014         0.000         0.017     0.176        0.089 0.296
   Attended_2016         0.002         0.000         0.024     0.077        0.063 0.166
   NotAttended           0.000         0.000         0.000     0.000        0.000 0.000
   Sum                   0.069         0.002         0.060     0.582        0.285 0.998

6. Multi-variate graphical - Categorical

Use tile plot to show multivariate categorical

# Note have to calculate and provide a variable for filling the graph
sea_reign_data %>%
  group_by(att_most_pref_time, att_attend_2016) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(att_most_pref_time, att_attend_2016)) + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  geom_tile(aes(fill = -count))

sea_reign_data %>%
  group_by(sales_tkt_type_2017, att_attend_2017) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(sales_tkt_type_2017, att_attend_2017)) + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  geom_tile(aes(fill = -count))

sea_reign_data %>%
  group_by(media_web, att_attend_2017) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(media_web, att_attend_2017)) + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  geom_tile(aes(fill = -count))

sea_reign_data %>%
  group_by(mer_buy_pref, att_attend_2016) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(mer_buy_pref, att_attend_2016)) + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  geom_tile(aes(fill = -count))

  • Sunday evenings is most popular timing
  • Single matches and seasonal tickets are most likely to sell

7. Multivariate non-graphical - Quantitative

Correlations plots

# Use ggpairs from the GGally package
cor_plot <- sea_reign_data %>%
  select(att_distance,sales_exp_self2016,sales_numofmatch_2017)   
cor(cor_plot)
                      att_distance sales_exp_self2016 sales_numofmatch_2017
att_distance            1.00000000         0.05155513             -0.102486
sales_exp_self2016      0.05155513         1.00000000              0.340335
sales_numofmatch_2017  -0.10248605         0.34033502              1.000000
  • People who are likely to attend certain number of matches in 2017 and dollar amount people have spent over the (2016) season on Seattle Reign FC merchandise and swag (not food) for self are positively correlated (34.2%)

8. Multivariate graphical - Quantitative

Correlations pariwise plot

# Pairwise plot
pairs_plot <- sea_reign_data %>%
  select(att_distance,sales_exp_self2016,sales_numofmatch_2017)
pairs_plot %>%
  ggpairs()

pairs.panels(pairs_plot)

Observations of the data

With more people likely to attend a 2017 matches, there are chances that people might spend more on merchandise as in 2016

# Standard scatter plot to visualize what is the revenue when producers receive maximum promos and ads
grid.arrange(
  sea_reign_data %>% 
    ggplot(aes(x = att_attend_2016, y = sales_numofmatch_2017, color = dem_gender)) +
    geom_point() + 
    geom_jitter() +
    geom_smooth(method = "lm", se = FALSE),
  sea_reign_data %>% 
    ggplot(aes(x = att_attend_2017, y = sales_numofmatch_2017, color = dem_gender)) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    geom_point() +
    geom_jitter() +
    scale_fill_brewer(palette = "Reds") +
    geom_smooth(method = "lm", se = FALSE),
    
  ncol = 2
)

  • Female have attended more matches in the past, in 2017 females are likely to attend more as well

9. Multivariate non-graphical - Categorical and Quantitative

# Form table of medians 
# Attendance when 2016 = 1 
attendance_2016 <- sea_reign_data %>%
  group_by(mer_buy_pref, dem_gender) %>%
  filter(att_attend_2016 == 1) %>%
  summarise(Sum_distance = mean(att_distance)) %>%
  spread(dem_gender, Sum_distance) %>%
  as.data.frame()
attendance_2016
  • Observation when attended match in 2016 = 1
  • Female who has attended a 2016 match and has a buying preference at store travelled approximately 18.6 miles to see the match

10. Multivariate non-graphical - Categorical and Quantitative

Part1 - Clustered barplots across attendance, media and merchandise

1. Across Merchandise

Clustered barplot to compare distance travelled, expenditure on self, number of matches attending in 2017 across Merchandise

# First get the data and name the graph so we can build it by layer
merchandise_data1 <- sea_reign_data %>%
  select(att_distance,mer_buy_pref) %>% 
  group_by(mer_buy_pref) %>%                      # Group_by is by factor level, so group by attendance
  summarise_all(funs(mean)) %>%             # Take the mean of all remaining columns so we can graph them
  gather("Variable", "Mean", -(mer_buy_pref))     # gather is used to reshape the data, make a bar graph by "Variable"
merchandise_data2 <- sea_reign_data %>%
  select(sales_exp_self2016,mer_buy_pref) %>% 
  group_by(mer_buy_pref) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(mer_buy_pref))
merchandise_data3 <- sea_reign_data %>%
  select(sales_exp_oth2016,mer_buy_pref) %>% 
  group_by(mer_buy_pref) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(mer_buy_pref))
merchandise_data4 <- sea_reign_data %>%
  select(sales_numofmatch_2017,mer_buy_pref) %>% 
  group_by(mer_buy_pref) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(mer_buy_pref))
merchandise_data5 <- sea_reign_data %>%
  select(att_distance,sales_exp_self2016,sales_numofmatch_2017,mer_buy_pref) %>% 
  group_by(mer_buy_pref) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(mer_buy_pref))
merchandise_data1
merchandise_data2
merchandise_data3
merchandise_data4
# Now set frame for plot, notice new variables "Variable" and "Mean"
grid.arrange(
merchandise_plot1 <- merchandise_data1 %>%  
  ggplot(aes(x = Variable, y = Mean, fill = mer_buy_pref)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"), # Set stat and position to get side-by-side bar
merchandise_plot2 <- merchandise_data2 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = mer_buy_pref)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"),
merchandise_plot3 <- merchandise_data3 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = mer_buy_pref)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"),
merchandise_plot4 <- merchandise_data4 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = mer_buy_pref)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"))

merchandise_plot5 <- merchandise_data5 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = mer_buy_pref)) +
    geom_bar(stat = "identity", position = "dodge")

Observations

  • People who have spent most on self in 2016 season are most likely to purchase merchandise at stores
  • People who are planning to attend a match in 2017 are most likely to purchase merchandise at stores

2. Across Media

Clustered barplot to compare distance travelled, expenditure on self, number of matches attending in 2017 for Media

media_data1 <- sea_reign_data %>%
  select(att_distance,media_web) %>% 
  group_by(media_web) %>%                      # Group_by is by factor level, so group by media
  summarise_all(funs(mean)) %>%             # Take the mean of all remaining columns so we can graph them
  gather("Variable", "Mean", -(media_web))     # gather is used to reshape the data, make a bar graph by "Variable"
media_data2 <- sea_reign_data %>%
  select(sales_exp_self2016,media_web) %>% 
  group_by(media_web) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(media_web))
media_data3 <- sea_reign_data %>%
  select(sales_exp_oth2016,media_web) %>% 
  group_by(media_web) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(media_web))
media_data4 <- sea_reign_data %>%
  select(sales_numofmatch_2017,media_web) %>% 
  group_by(media_web) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(media_web))
media_data5 <- sea_reign_data %>%
  select(att_distance,sales_exp_self2016,sales_numofmatch_2017,media_web) %>% 
  group_by(media_web) %>% 
  summarise_all(funs(mean)) %>% 
  gather("Variable", "Mean", -(media_web))
media_data1
media_data2
media_data3
media_data4
# Set frame for plot, notice new variables "Variable" and "Mean"
grid.arrange(
media_plot1 <- media_data1 %>%  
  ggplot(aes(x = Variable, y = Mean, fill = media_web)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"), # Set stat and position to get side-by-side bar
media_plot2 <- media_data2 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = media_web)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"),
media_plot3 <- media_data3 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = media_web)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"),
media_plot4 <- media_data4 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = media_web)) +
  scale_fill_brewer(palette = "PuBuGn") +
    geom_bar(stat = "identity", position = "dodge"))

media_plot5 <- media_data5 %>% 
  ggplot(aes(x = Variable, y = Mean, fill = media_web)) +
    geom_bar(stat = "identity", position = "dodge")

Observations

  • People who follow Reign on Instagram are travelling maximum distance to attend the game _ People who did maximum expenditure in season 2016, follow Reigns on Twitter
  • People who are likely to attend season 2017, follow Reigns on Instagram

Part2 - Clustered barplot with professional graphs

Lets add a title and some bar text

      # Add labels to each bar
merchandise_plot <- merchandise_plot5 + geom_text(aes(label = round(Mean, 1)), vjust = -0.5, color = "black",
            position = position_dodge(.9), size = 4) +
      # Add a main title
    ggtitle("Comparison of distance,expenditure and matches in 2017 by buying preference",
    subtitle = "Highest mean expenditure on self in 2016 season is at store\nHighest mean distance travelled to purchase merchandise in store") +
    scale_fill_brewer(palette = "PuBuGn") +
    theme(axis.ticks.x = element_blank(), # Use theme to clean up the graph to make more professional
          axis.title.x = element_blank(),
          axis.text.y = element_blank(),
          axis.ticks.y = element_blank(),
          panel.background = element_blank())
# Call the graph
merchandise_plot

      # Add labels to each bar
media_plot <- media_plot5 + geom_text(aes(label = round(Mean, 1)), vjust = -0.5, color = "black",
            position = position_dodge(.9), size = 3) +
      # Add a main title
    ggtitle("Comparison of distance,expenditure and matches in 2017 by buying preference",
    subtitle = "Highest mean expenditure on self in 2016 season is at store\nHighest mean distance travelled to purchase merchandise in store") +
    scale_fill_brewer(palette = "PuBuGn") +
    theme(axis.ticks.x = element_blank(), # Use theme to clean up the graph to make more professional
          axis.title.x = element_blank(),
          axis.text.y = element_blank(),
          axis.ticks.y = element_blank(),
          panel.background = element_blank())
# Call the graph
media_plot

Part3 - Bar plots

a. Factors that have impact on attendance?

# Doing a subset of the table to just show variables of interest
timings_subset <- c("Wed Evenings", "Sunday Evenings","Sunday Afternoons 4pm","Friday Evenings", "Saturday Evenings", 
                    "Saturday Afternoons 4pm", "Saturday Afternoons 4pm","Saturday Afternoons 1pm")
past_year_attendance <- sea_reign_data %>%
  filter(att_most_pref_time %in% timings_subset)
attendance_plot <- past_year_attendance %>%
  group_by(att_most_pref_time, att_first_attend) %>%
  summarize(avg_distance = mean(att_distance)) 
  ggplot(data = attendance_plot, aes(x = reorder(att_most_pref_time, avg_distance), y = avg_distance , 
                                       fill = att_first_attend)) +
  scale_fill_brewer(palette = "PuBuGn") +
  geom_bar(stat="identity", position="dodge") +
  coord_flip()

b. Factors that have impact on attendance like timings of the match?

# Doing a subset of the table to just show variables of interest
timings_subset <- c("Wed Evenings", "Sunday Evenings","Sunday Afternoons 4pm","Friday Evenings", "Saturday Evenings", 
                    "Saturday Afternoons 4pm", "Saturday Afternoons 4pm","Saturday Afternoons 1pm")
next_year_attendance <- sea_reign_data %>%
  #filter(att_attend_2017 %in% attend_2017_subset) %>%
  filter(att_most_pref_time %in% timings_subset)
attendance_plot1 <- next_year_attendance %>%
  group_by(att_most_pref_time, att_attend_2017) %>%
  summarize(avg_distance = mean(att_distance)) 
  ggplot(data = attendance_plot1, aes(x = reorder(att_most_pref_time, avg_distance), y = avg_distance , 
                                       fill = att_attend_2017)) +
  scale_fill_brewer(palette = "PuBuGn") +
  geom_bar(stat="identity", position="dodge") +
  coord_flip()

c. Factors that have impact on attendance audiences like to watch the gamewith?

# Doing a subset of the table to just show variables of interest
gamewith_subset <- c("3 Match Pack","Single Match","I don't know","5 Match Pack","Season Ticket")
ticket_type <- sea_reign_data %>%
  filter(sales_ticket_type %in% gamewith_subset)
attendance_plot2 <- ticket_type %>%
  group_by(sales_ticket_type,att_gamewith) %>%
  summarize(avg_distance = mean(att_distance)) 
  ggplot(data = attendance_plot2, aes(x = reorder(sales_ticket_type, avg_distance), y = avg_distance , 
                                       fill = att_gamewith)) +
  scale_fill_brewer(palette = "PuBuGn") +
  geom_bar(stat="identity", position="dodge") +
  coord_flip()

d. How much did people spent on merchandise on self and others if they attended a match in 2016?

e. Merchandise preferences ?

# Doing a subset of the table to just show variables of interest
timings_subset <- c("Wed Evenings", "Sunday Evenings","Sunday Afternoons 4pm","Friday Evenings", "Saturday Evenings", 
                    "Saturday Afternoons 4pm", "Saturday Afternoons 4pm","Saturday Afternoons 1pm")
attend_2017_subset <- c("Attend_2017","Neutral")
next_year_attendance <- sea_reign_data %>%
  filter(att_attend_2017 %in% attend_2017_subset) %>%
  filter(att_most_pref_time %in% timings_subset)
merchandise_plot <- sea_reign_data %>%
  group_by(mer_reign, mer_buy_pref) %>%
  summarize(avg_expenditure = mean(sales_exp_self2016)) 
  ggplot(data = merchandise_plot, aes(x = reorder(mer_reign, avg_expenditure), y = avg_expenditure , 
                                       fill = mer_buy_pref)) +
  scale_fill_brewer(palette = "PuBuGn") +
  geom_bar(stat="identity", position="dodge") +
  coord_flip()

Research Questions

Question 1: Understand the merchandise buying preferences and average expenditure over the 2016 season for people who have attended 2016 season.

1. First examine the buying preferences of people who have attended the match in 2016 season

mer_subset <- c("During Match","Online","At Store")
mer_reign_subset <- c("Short_Sleeve_Shirt","Long_Sleeve_Shirt","Accessories","Jackets")
merchandise <- sea_reign_data %>%
  filter(mer_buy_pref %in% mer_subset) %>%
  filter(mer_reign %in% mer_reign_subset)
merchandise %>% 
  filter(att_attend_2016 == 1) %>%
  group_by(mer_buy_pref) %>% 
  summarise(Count = n(),
  Average_Expenditure_Self = mean(sales_exp_self2016),
  Average_Expenditure_Others = mean(sales_exp_oth2016)) %>%
  arrange(desc(Average_Expenditure_Self)) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive")) %>%
  row_spec(1, background = "#e5f5e0")
mer_buy_pref Count Average_Expenditure_Self Average_Expenditure_Others
During Match 108 51.89815 45.87963
Online 120 50.12500 45.75000
At Store 23 47.60870 49.13043

Null Hypothesis: Average expedinture is same across all merchandise for people who attended season 2016

sea_hyp1 <- merchandise %>%
  filter(att_attend_2016 == 1) 
# Is expenditure the same across merchandises?
t.test(sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "During Match"], 
       sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "At Store"])

    Welch Two Sample t-test

data:  sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "During Match"] and sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "At Store"]
t = 0.37525, df = 39.158, p-value = 0.7095
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -18.82901  27.40792
sample estimates:
mean of x mean of y 
 51.89815  47.60870 
sea_hyp1 <- merchandise %>%
  filter(att_attend_2016 == 1) 
# Is expenditure the same across merchandises?
t.test(sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "During Match"], 
       sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "Online"])

    Welch Two Sample t-test

data:  sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "During Match"] and sea_hyp1$sales_exp_self2016[sea_hyp1$mer_buy_pref == "Online"]
t = 0.2229, df = 222.46, p-value = 0.8238
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -13.90322  17.44951
sample estimates:
mean of x mean of y 
 51.89815  50.12500 
#Graphing the Merchandise preferences and mean expenditure on self.
# 90% CI, get z-value for upper tail, use .95 since is one sided
z <- qnorm(.95)
# Incorporate CI into bar graph of means
sea_hyp1 %>%
  group_by(mer_buy_pref) %>%
  summarise(m = mean(sales_exp_self2016), sd = sd(sales_exp_self2016), 
            n = n(), ci = z * sd/sqrt(n)) %>%
  ggplot(aes(x = reorder(mer_buy_pref,m), y = m)) +
  geom_bar(stat = "identity", position = "dodge", fill = "#9ecae1") +
  geom_errorbar(aes(ymin = m - ci, ymax = m + ci), 
                width = 0.5, position = position_dodge(0.9)) +
  theme_classic() +
  xlab("") +
  ylab("") +
  scale_fill_brewer(palette = "PuBuGn") +
  theme(axis.ticks.x = element_blank(),
          axis.title.x = element_blank(),
          axis.ticks.y = element_blank()) +
  ggtitle("Merchandise preferences and mean expenditure on self",
          subtitle = "Maximum expenditure during match")

  • The expenditure graph above shows that the Merchandises are more likely to sell Online or during the Match

Question 2: Which type of ticket sells the most and at what timings of the day fans like to attend the match?

1. First examine the ticket preferences of people who are planning to attend matches in season 2017

# The palette with purples:
cbPalette <- c("#dddaed","#c5b4e3", "#9578d3", "#7d55c7")
#Table for ticket type for effectiveness across the whole market.
ticket_subset <- c("3 Match Pack","5 Match Pack","Season Ticket","Single Match")
ticket_t1 <- sea_reign_data %>%
  filter(sales_tkt_type_2017 %in% ticket_subset) 
ticket_t1 %>% 
  group_by(sales_tkt_type_2017) %>% 
  summarise(Count = n(),
  Total_matches2017 = sum(sales_numofmatch_2017)) %>%
  arrange(desc(Total_matches2017)) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive")) %>%
  row_spec(1, background = "#e5f5e0")
sales_tkt_type_2017 Count Total_matches2017
Season Ticket 134 1428
Single Match 186 560
5 Match Pack 30 159
3 Match Pack 21 75

Null Hypothesis: People who are planning to attend season 2017, would like to buy all types of tickets

sea_hyp2 <- ticket_t1 %>%
  filter(att_attend_2017 == 1) 
# Is ticket type same for everyone who is attending match in 2017?
t.test(sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "5 Match Pack"], 
       sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "Season Ticket"])

    Welch Two Sample t-test

data:  sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==  and sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==     "5 Match Pack"] and     "Season Ticket"]
t = -15.32, df = 62.313, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -5.939197 -4.568322
sample estimates:
mean of x mean of y 
 5.392857 10.646617 
sea_hyp2 <- ticket_t1 %>%
  filter(att_attend_2017 == 1) 
# Is ticket type same for everyone who is attending match in 2017?
t.test(sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "5 Match Pack"], 
       sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "Single Match"])

    Welch Two Sample t-test

data:  sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==  and sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==     "5 Match Pack"] and     "Single Match"]
t = 6.9298, df = 44.918, p-value = 1.307e-08
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 1.534338 2.791749
sample estimates:
mean of x mean of y 
 5.392857  3.229814 
sea_hyp2 <- ticket_t1 %>%
  filter(att_attend_2017 == 1) 
# Is ticket type same for everyone who is attending match in 2017?
t.test(sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "5 Match Pack"], 
       sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 == "3 Match Pack"])

    Welch Two Sample t-test

data:  sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==  and sea_hyp2$sales_numofmatch_2017[sea_hyp2$sales_tkt_type_2017 ==     "5 Match Pack"] and     "3 Match Pack"]
t = 3.5914, df = 31.398, p-value = 0.001107
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.8071108 2.9259720
sample estimates:
mean of x mean of y 
 5.392857  3.526316 
#Graphing the relationship between in-store promotions and revenue across companies.
# 90% CI, get z-value for upper tail, use .95 since is one sided
z <- qnorm(.95)
# Incorporate CI into bar graph of means
sea_hyp2 %>%
  group_by(sales_tkt_type_2017) %>%
  summarise(m = mean(sales_numofmatch_2017), sd = sd(sales_numofmatch_2017), 
            n = n(), ci = z * sd/sqrt(n)) %>%
  ggplot(aes(x = reorder(sales_tkt_type_2017,m), y = m)) +
  geom_bar(stat = "identity", position = "dodge", fill = "#9ecae1") +
  geom_errorbar(aes(ymin = m - ci, ymax = m + ci), 
                width = 0.5, position = position_dodge(0.9)) +
  theme_classic() +
  xlab("") +
  ylab("") +
  theme(axis.ticks.x = element_blank(),
          axis.title.x = element_blank(),
          axis.ticks.y = element_blank()) +
  # To use for fills, add
  scale_fill_manual(values=cbPalette) +
  ggtitle("Average number of ticket people are planning buy for season 2017",
          subtitle = "Season ticket is likely to sell the most")

  • The figure above indicates that Season ticket is predicted to sell highest for the upcoming Season 2017
  • 5 Match Pack is least likely to sell

Summary of EDA

Possible Recommendations

Possible recommendations for Seattle Reign FC to increase ticket sales and attendance:

  • Purchasing habits of visitors, most likely to purchase from stores

  • Seattle Reign FC can focus on sales of Short Sleeve Shirts during the match because it is most selling merchandise for all sponsors

  • Since, only College Graduates are likely to attend matches on Saturday Afternoons 1pm, it is important to find out reasons of why the College and Graduate students are not attending the match, is the distance of stadium far from the city to attend with family?

Statistical Analysis

1. Cross-tab of Buying preference and purchase sponsors

Check number of observations in each Category-Region pair

# Number of observations helps us determine if stats will be valid
sea_reign_data %>% 
  tabyl(mer_buy_pref, mer_purchase_sponsors) %>% 
  adorn_totals(where = c("row", "col"))
 mer_buy_pref BECU Carter Subaru Kraken Congee Microsoft Not sure Pepsi Ruffneck Scarves Total
     At Store    0             1             0         9        8     8                0    26
 During Match   15             6             5        41       21    23                5   116
      Neutral   15             6             3        43       44    17                2   130
       Online   15             7             0        61       24    32                3   142
        Total   45            20             8       154       97    80               10   414

Large enough number of observations for each cell indicate sample results will be statistically valid

  • Assuming this is a representative sample

2. Chi-square of Buying preference and purchase sponsors

  • Tell if there is a pattern for which sponsors have buying preference
    • Are the factor levels independent
  • Null hypothesis: Are all cells the same
# Are Category and Region sales similar?
# Not tidyverse so have to use base code
chisq.test(table(sea_reign_data$mer_buy_pref, sea_reign_data$mer_purchase_sponsors))
Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  table(sea_reign_data$mer_buy_pref, sea_reign_data$mer_purchase_sponsors)
X-squared = 30.777, df = 18, p-value = 0.03054
  • Statistical measures
    • p-value: Small p-value; reject the null hypothesis
    • chi-square: High value; reject the null hypothesis
  • Confidence intervals
    • Because is a sample we cannot be sure our descriptive statistics are representative of the population
    • Use CI of given level of significance to assess the reliability of results
    • CI are good for visualization

3. Significance of correlation

  • Null hypothesis: self and other expenditure sold are not correlated
# Are the correlations statistically significant?
# Not tidyverse so have to use base code
cor.test(sea_reign_data$sales_exp_oth2016, sea_reign_data$sales_exp_self2016)

    Pearson's product-moment correlation

data:  sea_reign_data$sales_exp_oth2016 and sea_reign_data$sales_exp_self2016
t = 2.3786, df = 412, p-value = 0.01783
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.02023787 0.21040629
sample estimates:
      cor 
0.1163887 
  • Statistical measures
    • p-value: small p-value, we reject the null
    • t-stat: large, reject the null

4. Table of proportions with confidence intervals

  • Factor variable descriptive statistics
    • Count - does not generalize from sample to population
    • Proportion - is a good descriptive stat
# Table of counts to calculate the confidence interval
P_B_n <- sea_reign_data %>% 
  group_by(mer_buy_pref, mer_purchase_sponsors) %>% 
  summarise(n = n())
# Calulate confidence intervals using mulitnomialCI           
P_B_n_ci <- multinomialCI(t(P_B_n[, 3]), 0.05) # use t() to transpose the count table
                                               # alpha = 0.05 indicates 95% confidence level
# Table with proportions  
P_B_table <- sea_reign_data %>% 
  group_by(mer_buy_pref, mer_purchase_sponsors) %>% 
  summarise(prop = n()/sum(nrow(sea_reign_data)))
# Add the confindence inervals to the table of proportions
P_B_table$ci_l <- P_B_n_ci[,1]
P_B_table$ci_u <- P_B_n_ci[,2]
# Show the table
(P_B_table)

5. Incorporate CI into bar graph of means

#Graphing mean promotional revenue across General Mill branded cereals.
# 90% CI, get z-value for upper tail, use .95 since is one sided
z <- qnorm(.95)
# Incorporate CI into bar graph of means
sea_st %>%
  mutate(promo = if_else(att_promo_effect == "Positive influence", "Positive", "None")) %>%
  mutate(pref_time = case_when(att_most_pref_time == "Friday Evenings" ~ "Fri Evenings",
                               att_most_pref_time == "Saturday Afternoons 4pm" ~ "Sat Aft4pm",
                               att_most_pref_time == "Sunday Afternoons 4pm" ~ "Sun Aft4pm",
                               att_most_pref_time == "Saturday Afternoons 1pm" ~ "Sat Aft1pm",
                               att_most_pref_time == "Sunday Evenings" ~ "Sun Evenings")) %>%
  group_by(pref_time, promo) %>%
  summarise(m = mean(sales_numofmatch_2017), sd = sd(sales_numofmatch_2017)/5, 
            n = n(), ci = z * sd/sqrt(n)) %>%
  ggplot(aes(x = reorder(pref_time, m), y = m, fill = reorder(promo,m))) +
  geom_bar(stat = "identity", position = "dodge") +
  geom_errorbar(aes(ymin = m - ci, ymax = m + ci), 
                width = 0.5, position = position_dodge(0.9)) +
  
#  coord_flip() +
  theme_classic() +
  xlab("") +
  labs(fill = "Promo Effect") +
  theme(axis.text.x = element_text(angle = 30, hjust = 1)) +
  theme(axis.text = element_text(face = "bold", size = 11),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.title = element_blank(),
        legend.position = "top",
        legend.title = element_text(face = "bold")) +
  # To use for fills, add
  scale_fill_manual(values=cbPalette) +
  ggtitle("Mean number of Season Tickets likely to sell in Season 2017",
          subtitle = "Promos are not effective on weekend matches")

  • Interpretations

    1. All proportions are reliably greater than zero
    2. Sat Afternoons 1pm tickets are likely to sell most practically and reliably
  • Cleaner graph

# The palette with purples:
cbPalette <- c("#dddaed","#c5b4e3", "#9578d3", "#7d55c7")
base_plot5 <- 
sea_st %>%
  mutate(promo = if_else(att_promo_effect == "Positive influence", "Positive", "None")) %>%
  mutate(pref_time = case_when(att_most_pref_time == "Friday Evenings" ~ "Fri Evenings",
                               att_most_pref_time == "Saturday Afternoons 4pm" ~ "Sat Aft4pm",
                               att_most_pref_time == "Sunday Afternoons 4pm" ~ "Sun Aft4pm",
                               att_most_pref_time == "Saturday Afternoons 1pm" ~ "Sat Aft1pm",
                               att_most_pref_time == "Sunday Evenings" ~ "Sun Evenings")) %>%
  group_by(pref_time, promo) %>%
  summarise(m = mean(sales_numofmatch_2017), sd = sd(sales_numofmatch_2017)/5, 
            n = n(), ci = z * sd/sqrt(n)) %>%
  ggplot(aes(x = reorder(pref_time, m), y = m, fill = promo)) +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(aes(label = round(m, 1)), vjust = -0.5, color = "black",
            position = position_dodge(.9), size = 2.5) +
#  coord_flip() +
  theme_classic() +
  xlab("") +
  ylab("Mean") +
  labs(fill = "Promo Effect") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  theme(axis.text = element_text(face = "bold", size = 11),
        axis.ticks.x = element_blank(),
        axis.title.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        legend.position = "top",
        legend.title = element_text(face = "bold")) +
  scale_fill_manual(values=cbPalette) +
  ggtitle("Predicted Mean number of Season Tickets likely to sell in Season 2017",
          subtitle = "Promos are statistically effective on Sat afternoon only")

select(factor1_attend,att_first_attend,att_interest,att_gamewith,att_travel_mode,att_distance, att_promo_effect,att_player_fan,att_seaEvent, att_most_pref_time, att_least_preferred_timing,att_attend_2017,att_attend_2016, att_gamewith, sales_ticket_type, sales_exp_self2016, sales_exp_oth2016,sales_numofmatch_2017,sales_tkt_type_2017,media_web, media_season_newspaper,media_season_tv, mer_buy_pref,cost, mer_purchase_sponsors,mer_reign,dem_gender,dem_sexualOrient,dem_marital_status, dem_education,sat_gameday,satisfacn_perf) %>% drop_na()

6. Multiple linear regression

  • Multiple linear regression controls for all variables simultaneously

# Linear regression
# Interaction term units and promo because number of units and promotions could affect revenue (approximately 20percent correlated)
base <- lm(sales_exp_self2016 ~ sales_numofmatch_2017 + sales_tkt_type_2017 + mer_buy_pref + mer_purchase_sponsors + mer_reign
           + dem_education,
            data = sea_reign_data)

# Review output
summary(base)

Observations

  • R2 is 0.2301 means the model can explain 23.01% variability in the dependent variable Expenditure
  • Controlling other variable, mer_reignNo preferences, mer_reignShort_Sleeve_Shirt and mer_purchase_sponsorsRuffneck Scarves have p-vales of 5% level(p<0.01).
# plot residuals to check for patterns
par(mfrow = c(1, 1))
plot(sea_reign_data$sales_exp_self2016, base$residuals)

plot(sea_reign_data$sales_numofmatch_2017, base$residuals)

plot(sea_reign_data$att_distance, base$residuals)

7.Visualization of Multiple Regression

How easy is it to understand which variables are:

  1. Most statistically significant
  2. Have the largest impact

a. Table format

# Pull out the coefficients and confidence interval for table and graph
coe <- summary(base)$coefficients # get coefficients and related stats
coe_CI <- as.data.frame(cbind(coe[-1, ], confint(base)[-1, ])) # find and bind CI, remove Intercept 
# Rename results data frame
names(coe_CI) <- c("estimate", "se", "t", "pval","low_CI","high_CI") 
htmlTable(round(coe_CI,3))
estimate se t pval low_CI high_CI
sales_numofmatch_2017 1.946 1.147 1.696 0.091 -0.309 4.202
sales_tkt_type_20175 Match Pack 24.624 14.586 1.688 0.092 -4.053 53.301
sales_tkt_type_2017Pitchside Table 5.365 28.469 0.188 0.851 -50.606 61.336
sales_tkt_type_2017Season Ticket 21.969 14.166 1.551 0.122 -5.881 49.82
sales_tkt_type_2017Single Match -9.222 11.596 -0.795 0.427 -32.021 13.578
sales_tkt_type_2017Undecided 1.938 13.772 0.141 0.888 -25.139 29.015
mer_buy_prefDuring Match -2.554 11.237 -0.227 0.82 -24.647 19.539
mer_buy_prefNeutral -18.256 11.068 -1.65 0.1 -40.016 3.503
mer_buy_prefOnline -5.186 11.024 -0.47 0.638 -26.86 16.488
mer_purchase_sponsorsCarter Subaru 8.206 13.598 0.603 0.547 -18.529 34.942
mer_purchase_sponsorsKraken Congee -2.719 19.437 -0.14 0.889 -40.934 35.496
mer_purchase_sponsorsMicrosoft 8.176 8.696 0.94 0.348 -8.921 25.273
mer_purchase_sponsorsNot sure -10.841 9.615 -1.127 0.26 -29.745 8.063
mer_purchase_sponsorsPepsi 10.31 9.539 1.081 0.28 -8.444 29.063
mer_purchase_sponsorsRuffneck Scarves 44.222 17.605 2.512 0.012 9.608 78.835
mer_reignJackets 2.313 16.526 0.14 0.889 -30.179 34.805
mer_reignLong_Sleeve_Shirt 17.816 13.129 1.357 0.176 -7.997 43.629
mer_reignNo preferences 32.597 12.655 2.576 0.01 7.717 57.477
mer_reignShort_Sleeve_Shirt 26.169 11.207 2.335 0.02 4.135 48.202
dem_educationGraduate Degree -0.707 5.456 -0.13 0.897 -11.435 10.021
dem_educationHigh School Graduate 27.008 19.717 1.37 0.172 -11.757 65.773
dem_educationOther 57.663 35.918 1.605 0.109 -12.954 128.281
dem_educationSome College 11.184 8.441 1.325 0.186 -5.411 27.779

b. Table: Order based on p-value

# Make a neat table
htmlTable(round(coe_CI[order(coe_CI$pval, decreasing = FALSE), ], 3))
estimate se t pval low_CI high_CI
mer_reignNo preferences 32.597 12.655 2.576 0.01 7.717 57.477
mer_purchase_sponsorsRuffneck Scarves 44.222 17.605 2.512 0.012 9.608 78.835
mer_reignShort_Sleeve_Shirt 26.169 11.207 2.335 0.02 4.135 48.202
sales_numofmatch_2017 1.946 1.147 1.696 0.091 -0.309 4.202
sales_tkt_type_20175 Match Pack 24.624 14.586 1.688 0.092 -4.053 53.301
mer_buy_prefNeutral -18.256 11.068 -1.65 0.1 -40.016 3.503
dem_educationOther 57.663 35.918 1.605 0.109 -12.954 128.281
sales_tkt_type_2017Season Ticket 21.969 14.166 1.551 0.122 -5.881 49.82
dem_educationHigh School Graduate 27.008 19.717 1.37 0.172 -11.757 65.773
mer_reignLong_Sleeve_Shirt 17.816 13.129 1.357 0.176 -7.997 43.629
dem_educationSome College 11.184 8.441 1.325 0.186 -5.411 27.779
mer_purchase_sponsorsNot sure -10.841 9.615 -1.127 0.26 -29.745 8.063
mer_purchase_sponsorsPepsi 10.31 9.539 1.081 0.28 -8.444 29.063
mer_purchase_sponsorsMicrosoft 8.176 8.696 0.94 0.348 -8.921 25.273
sales_tkt_type_2017Single Match -9.222 11.596 -0.795 0.427 -32.021 13.578
mer_purchase_sponsorsCarter Subaru 8.206 13.598 0.603 0.547 -18.529 34.942
mer_buy_prefOnline -5.186 11.024 -0.47 0.638 -26.86 16.488
mer_buy_prefDuring Match -2.554 11.237 -0.227 0.82 -24.647 19.539
sales_tkt_type_2017Pitchside Table 5.365 28.469 0.188 0.851 -50.606 61.336
sales_tkt_type_2017Undecided 1.938 13.772 0.141 0.888 -25.139 29.015
mer_reignJackets 2.313 16.526 0.14 0.889 -30.179 34.805
mer_purchase_sponsorsKraken Congee -2.719 19.437 -0.14 0.889 -40.934 35.496
dem_educationGraduate Degree -0.707 5.456 -0.13 0.897 -11.435 10.021
  • The p of 0 means that the results are highly significant, it suggests there was absolutely no or zero chance of getting the results if the null hypothesis was true

c. Cleveland dot plot

# Cleveland dot plot of results
ggplot(coe_CI, aes(x = estimate, y = row.names(coe_CI))) +
  geom_point(size = 3) +
  xlim(min(coe_CI$low_CI), max(coe_CI$high_CI)) +
  ylab("Variable") +
  xlab("Coefficient") +
  theme_bw()

d. Cleveland dot plot - Order based on p-value

This will order by most statistically significant

# Reorder for more clarity
(g1 <- ggplot(coe_CI, aes(x = estimate, y = reorder(row.names(coe_CI),desc(pval)))) +
  geom_point(size = 3) +
  xlim(min(coe_CI$low_CI), max(coe_CI$high_CI)) +
  ylab("Variable") +
  xlab("Coefficient") +
  theme_bw() 
)

NA

8. How about include CI

  • Visualize which variables have coefficients statistically different from zero
# Use geom_segment to illustrate CI
(g2 <- g1 +
  geom_segment(aes(yend = reorder(row.names(coe_CI),desc(pval))), 
               xend = coe_CI$high_CI, color = "Blue") +
  geom_segment(aes(yend = reorder(row.names(coe_CI),desc(coe_CI$pval))), 
               xend = coe_CI$low_CI, color = "Blue") +
   xlab("Coefficient with Confidence Interval")
)

  • Vertical line at 0
  • Volume, interaction term adNONE:units, adB:units do not have CI bar
  • The p-value for each term tests the null hypothesis that the coefficient is equal to zero (no effect)
# Line at 0 gives context
(g3 <- g2 +
  geom_vline(xintercept = 0, color = "red"))

Summary of findings

  • If a 95% confidence interval includes the null value, then there is no statistically meaningful or statistically significant difference between the groups
  • All variables have CI bar
  • dem_educationOther has highest CI bar, more statistically significant
LS0tCnRpdGxlOiAiU2VhdHRsZV9SZWlnbkZDX0Nhc2VfU3R1ZHkiCmF1dGhvcjogIkFua2l0YSBQYXRoYWsiCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCIKb3V0cHV0OgogICBodG1sX25vdGVib29rOgogICAgIHRvYzogdHJ1ZQogICAgIHRvY19mbG9hdDoKICAgICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQogICAgIHRvY19kZXB0aDogNAotLS0KCkNsZWFyIEVudmlyb25tZW50Cj09PT09PT09PT09PT09PT09CgpgYGB7cn0KIyBDbGVhciBlbnZpcm9ubWVudCBvZiB2YXJpYWJsZXMgYW5kIGZ1bmN0aW9ucwpybShsaXN0ID0gbHMoYWxsID0gVFJVRSkpIAoKIyBDbGVhciBlbnZpcm9ubWV0IG9mIHBhY2thZ2VzCmlmKGlzLm51bGwoc2Vzc2lvbkluZm8oKSRvdGhlclBrZ3MpID09IEZBTFNFKWxhcHBseShwYXN0ZSgicGFja2FnZToiLCBuYW1lcyhzZXNzaW9uSW5mbygpJG90aGVyUGtncyksIHNlcD0iIiksIGRldGFjaCwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFLCB1bmxvYWQgPSBUUlVFKQpgYGAKCkxvYWQgUGFja2FnZXMKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmBgYHtyIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkgICAgICMgRm9yIHdyYW5nbGluZywgc3Vic2V0aW5nLCBhbmQgcGxvdGluZwpsaWJyYXJ5KGx1YnJpZGF0ZSkgICAgICMgRm9yIHdvcmtpbmcgd2l0aCBkYXRlcwpsaWJyYXJ5KHN0cmluZ3IpICAgICAgICAjIFVzZWQgdG8gbWFuaXB1bGF0ZSBzdHJpbmdzCmxpYnJhcnkoR0dhbGx5KSAgICAgICAgIyBGb3IgZ2dwYWlycywgYSBkZXRhaWxlZCBjb3JyZWxhdGlvbiBncmFwaGljCmxpYnJhcnkoZ3JpZEV4dHJhKSAgICAgIyBGb3IgZ3JvdXBpbmcgZ3JhcGhzCmxpYnJhcnkoamFuaXRvcikgICAgICAgIyBUaWR5IGNyb3NzIHRhYnMKbGlicmFyeShNdWx0aW5vbWlhbENJKSAjIFRvIGNhbGN1bGF0ZSBtdWx0aW5vbWlhbCBjb25maWRlbmNlIGludGVydmFscyAgCmxpYnJhcnkoaHRtbFRhYmxlKSAgICAgIyBUbyBmb3JtYXQgaHRtbCB0YWJsZXMKbGlicmFyeShwc3ljaCkKbGlicmFyeShmbGV4ZGFzaGJvYXJkKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKU3RhbmRhcmQgRURBIFByb2Nlc3MKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCjEuIFVuaXZhcmlhdGUgbm9uLWdyYXBoaWNhbCAgCiAgIC0gY2F0ZWdvcmljYWwgKGkuZS4gKipmYWN0b3IqKikgICAKICAgICAgLSBjb3VudCwgcHJvcG9ydGlvbiwgcGVyY2VudGFnZSAgCiAgIC0gcXVhbnRpdGF0aXZlICAgCiAgICAgIC0gY2VudHJhbCB0ZW5kYW5jeSwgZGlzcGVyc2lvbiwgc2tld25lc3MsIGt1cnRvc2lzLCBldGMgIAoKMi4gVW5pdmFyaWF0ZSBncmFwaGljYWwgIAogICAtIGNhdGVnb3JpY2FsICAgIAogICAgICAtIGhpc3RvZ3JhbSBvciBiYXJwbG90IG9mIGZhY3RvcnMsIHBpZSBjaGFydCAgCiAgIC0gcXVhbnRpdGF0aXZlICAgCiAgICAgIC0gaGlzdG9ncmFtICh0cnkgZGlmZmVyZW50IGJpbikgb3IgZGVuc2l0eSwgYm94cGxvdCwgcXVhbnRpbGUtbm9ybWFsIHBsb3QgIAoKMy4gTXVsdGktdmFyaWF0ZSBub24tZ3JhcGhpY2FsICAKICAgLSBjYXRlZ29yaWNhbCAKICAgICAgLSBjcm9zcy10YWJsdWF0aW9uIGlmIG11bHRpcGxlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyAgIAogICAtIHF1YW50aXRhdGl2ZSAgIAogICAgICAtIGNvcnJlbGF0aW9uIChhbmQgY292YXJpYW5jZSkgIAoKNC4gTXVsdGktdmFyaWF0ZSBncmFwaGljYWwgIAogICAtIGNhdGVnb3JpY2FsICAgIAogICAgICAtIHRpbGUgZ3JhcGggIAogICAtIHF1YW50aXRhdGl2ZSAgIAogICAgICAtIHNjYXR0ZXIgcGxvdCwgY29ycmVsYXRpb24gcGxvdCAKICAgLSBjYXRlZ29yaWNhbCBhbmQgcXVhbnRpdGF0aXZlIAogICAgICAtIGRpc3RyaWJ1dGlvbiBvciBzdW1tYXJ5IG9mIHF1YW50aXRhdGl2ZSBieSBsZXZlbCBvZiBjYXRlZ29yaWNhbCB2YXJpYWJsZSAgCiAgICAgIC0gbXVsdGlwbGUgYm94cGxvdHMgIAogICAgICAtIHNjYXR0ZXIgcGxvdCB3aXRoIGNvbG9yLCBzaXplLCBvciBzaGFwZSBieSBmYWN0b3Igb3IgY29udGludW91cyB2YXJpYWJsZSAgCgoKTG9hZCBhbmQgcmV2aWV3IGRhdGEKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyMgV29yayB3aXRoIGRhdGFzZXRzCgogLSBMb2FkIGFuZCB3b3JrIHdpdGggc2VhdHRsZV9yZWlnbgoKYGBge3J9CiMgTG9hZCBkYXRhCnNlYXR0bGVfcmVpZ24gPC0gcmVhZC5jc3YoIlNlYXR0bGVfUmVpZ24uY3N2IikKCiMgV29yayB3aXRoIGEgY29weSBvZiBwcm9kX2RhdGEKc2VhdHRsZV9yZWlnbl9yYXdfZGF0YSA8LSBzZWF0dGxlX3JlaWduCgojIFJldmlldyBkYXRhIHN0cnVjdHVyZQojc3RyKHNlYXR0bGVfcmVpZ24pCgojc3VtbWFyeShzZWF0dGxlX3JlaWduKQoKYGBgCgpGaWx0ZXJpbmcgcmVxdWlyZWQgZGF0YQo9PT09PT09PT09PT09PT09PT09PT09PT09PQoKYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KCiMgRmlsdGVyaW5nIHJlcXVpcmVkIHZhcmlhYmxlcyBiYXNlZCBvbiB0aGUgZGF0YSBkaWN0aW9uYXJ5CiMgZmFjdG9yXzEgPSBhdHRlbmRhbmNlCiMgZmFjdG9yXzIgPSBzYWxlcwojIGZhY3Rvcl8zID0gbWVkaWEKIyBmYWN0b3JfNCA9IG1lcmNoYW5kaXNlCiMgZmFjdG9yXzUgPSBkZW1vZ3JhcGhpY3MKIyBmYWN0b3JfNiA9IHNhdGlzZmFjdGlvbgpzZWF0dGxlX3JlaWduIDwtIHNlYXR0bGVfcmVpZ25fcmF3X2RhdGEgJT4lCiAgbXV0YXRlKAogICAgICAgICBmYWN0b3IxX2F0dGVuZCA9IGFzLmZhY3RvcihBdHRlbmQxKSwKICAgICAgICAgYXR0X2ZpcnN0X2F0dGVuZCA9IGNhc2Vfd2hlbihBdHRlbmQyID09IDIwMTMgfiAiQXR0ZW5kZWRfMjAxMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdHRlbmQyID09IDIwMTQgfiAiQXR0ZW5kZWRfMjAxNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdHRlbmQyID09IDIwMTUgfiAiQXR0ZW5kZWRfMjAxNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdHRlbmQyID09IDIwMTYgfiAiQXR0ZW5kZWRfMjAxNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vdEF0dGVuZGVkIiksCiAgICAgICAgIGF0dF9maXJzdF9hdHRlbmQgPSBhcy5mYWN0b3IoYXR0X2ZpcnN0X2F0dGVuZCksCiAgICAgICAgIGF0dF9hdHRlbmRfMjAxNiA9IGNhc2Vfd2hlbihBdHRlbmQzID09ICJZZXMiIH4gIjEiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIwIiksCiAgICAgICAgIGF0dF9hdHRlbmRfMjAxNiA9IGFzLmZhY3RvcihhdHRfYXR0ZW5kXzIwMTYpLAogICAgICAgICBhdHRfaW50ZXJlc3QgPSBjYXNlX3doZW4oc3RyX2RldGVjdChJbnRlcmVzdCwiSSBsaXZlIGFuZCBkaWUgd2l0aCB0aGlzIHRlYW0iKSB+ICJEaWVfaGVhcnRfZmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChJbnRlcmVzdCwiSSBjb25zaWRlciBteXNlbGYgdG8gYmUgYSBsb3lhbCBmYW4gb2YgdGhpcyB0ZWFtIikgfiAiTG95YWxfZmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChJbnRlcmVzdCwiSSBjb25zaWRlciBteXNlbGYgdG8gYmUgYSBtb2RlcmF0ZSBmYW4gb2YgdGhpcyB0ZWFtIikgfiAiTW9kZXJhdGVfZmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChJbnRlcmVzdCwiSSBjb25zaWRlciBteXNlbGYgdG8gYmUgYSBsb3ctbGV2ZWwgZmFuIG9mIHRoaXMgdGVhbSIpIH4gIkxvd19sZXZlbF9mYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkxlc3NfaW50ZXJlc3QiKSwgCiAgICAgICAgIGF0dF9pbnRlcmVzdCA9IGFzLmZhY3RvcihhdHRfaW50ZXJlc3QpLAogICAgICAgICBhdHRfZ2FtZXdpdGggPSBjYXNlX3doZW4oR2FtZXdpdDEgPT0gMSB+ICJGYW1pbHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1ld2l0MiA9PSAxIH4gIkZyaWVuZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1ld2l0MyA9PSAxIH4gIkJ1c2luZXNzIEFzc29jaWF0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1ld2l0NCA9PSAxIH4gIkkgYXR0ZW5kIGdhbWVzIGJ5IG15c2VsZiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTm90QXBwbGljYWJsZSIpLAogICAgICAgICBhdHRfZ2FtZXdpdGggPSBhcy5mYWN0b3IoYXR0X2dhbWV3aXRoKSwKICAgICAgICAgYXR0X2Rpc3RhbmNlID0gKFRyYXZlbDUpLAogICAgICAgICBhdHRfdHJhdmVsX21vZGUgPSBhcy5mYWN0b3IoVHJhdmVsNiksCiAgICAgICAgIGF0dF9wcm9tb19lZmZlY3QgPSBjYXNlX3doZW4oc3RyX2RldGVjdChQcm9tbzEsIkhhcyBubyBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIk5vIGluZmx1ZW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChQcm9tbzEsIkhhcyBhIHBvc2l0aXZlIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiUG9zaXRpdmUgaW5mbHVlbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFByb21vMSwiSGFkIGEgbmVnYXRpdmUgaW5mbHVlbmNlIG9uIG15IGF0dGVuZGFuY2UiKSB+ICJOZWdhdGl2ZSBpbmZsdWVuY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiVW5rbm93biIpLAogICAgICAgICBhdHRfcHJvbW9fZWZmZWN0ID0gYXMuZmFjdG9yKGF0dF9wcm9tb19lZmZlY3QpLAogICAgICAgICBhdHRfcGxheWVyX2ZhbjEgPSBjYXNlX3doZW4oc3RyX2RldGVjdChJRHBsYXkxLCJBZ3JlZSIpIH4gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoSURwbGF5MSwiRGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KElEcGxheTEsIlNvbWV3aGF0IGRpc2FncmVlIikgfiAiMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChJRHBsYXkxLCJTb21ld2hhdCBhZ3JlZSIpIH4gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoSURwbGF5MSwiU3Ryb25nbHkgYWdyZWUiKSB+ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KElEcGxheTEsIlN0cm9uZ2x5IERpc2FncmVlIikgfiAiMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICIwIiksCiAgICAgICAgIAogICAgICAgICBhdHRfYXR0ZW5kXzIwMTdfMSA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KEF0dGVuZDE3LCJBZ3JlZSIpIH4gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQXR0ZW5kMTcsIkRpc2FncmVlIikgfiAiMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChBdHRlbmQxNywiU29tZXdoYXQgZGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEF0dGVuZDE3LCJTb21ld2hhdCBhZ3JlZSIpIH4gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQXR0ZW5kMTcsIlN0cm9uZ2x5IGFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChBdHRlbmQxNywiU3Ryb25nbHkgRGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIjAiKSwKICAgICAgICAgYXR0X3BsYXllcl9mYW4gPSBjYXNlX3doZW4oYXR0X3BsYXllcl9mYW4xID09IDEgfiAiUGxheWVyX0ZhbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfcGxheWVyX2ZhbjEgPT0gMiB+ICJOb3RfYV9QbGF5ZXJfRmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9wbGF5ZXJfZmFuMSA9PSAwIH4gIk5ldXRyYWwiKSwKICAgICAgICAgYXR0X2F0dGVuZF8yMDE3ID0gY2FzZV93aGVuKGF0dF9hdHRlbmRfMjAxN18xID09IDEgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfYXR0ZW5kXzIwMTdfMSA9PSAyIH4gIjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X2F0dGVuZF8yMDE3XzEgPT0gMCB+ICIwIiksCiAgICAgICAgIGF0dF9wbGF5ZXJfZmFuID0gYXMuZmFjdG9yKGF0dF9wbGF5ZXJfZmFuKSwKICAgICAgICAgYXR0X2F0dGVuZF8yMDE3ID0gYXMuZmFjdG9yKGF0dF9hdHRlbmRfMjAxNyksCiAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9IGNhc2Vfd2hlbihHYW1lVGltMT09MSB+ICJXZWQgRXZlbmluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1lVGltMT09MiB+ICJGcmlkYXkgRXZlbmluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1lVGltMT09MyB+ICJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdhbWVUaW0xPT00IH4gIlNhdHVyZGF5IEFmdGVybm9vbnMgNHBtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtZVRpbTE9PTUgfiAiU2F0dXJkYXkgRXZlbmluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1lVGltMT09NiB+ICJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1lVGltMT09NyB+ICJTdW5kYXkgRXZlbmluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vUHJlZmVyZW5jZSIpLAogICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPSBhcy5mYWN0b3IoYXR0X21vc3RfcHJlZl90aW1lKSwKICAgICAgICAgYXR0X2xlYXN0X3ByZWZlcnJlZF90aW1pbmcgPSBjYXNlX3doZW4oR2FtZVRpbTc9PTEgfiAiV2VkIEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtZVRpbTc9PTIgfiAiRnJpZGF5IEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtZVRpbTc9PTMgfiAiU2F0dXJkYXkgQWZ0ZXJub29ucyAxcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1lVGltNz09NCB+ICJTYXR1cmRheSBBZnRlcm5vb25zIDRwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdhbWVUaW03PT01IH4gIlNhdHVyZGF5IEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtZVRpbTc9PTYgfiAiU3VuZGF5IEFmdGVybm9vbnMgNHBtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtZVRpbTc9PTcgfiAiU3VuZGF5IEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJOb1ByZWZlcmVuY2UiKSwKICAgICAgICAgYXR0X2xlYXN0X3ByZWZlcnJlZF90aW1pbmcgPSBhcy5mYWN0b3IoYXR0X2xlYXN0X3ByZWZlcnJlZF90aW1pbmcpLAogICAgICAgICAKICAgICAgICAgc2FsZXNfdGlja2V0X3R5cGUgPSBhcy5mYWN0b3IobGFzdHR5cGUpLAogICAgICAgICBzYWxlc19udW1vZm1hdGNoXzIwMTcgPSAoR2FtZXBsbjEpLAogICAgICAgICBzYWxlc190a3RfdHlwZV8yMDE3ID0gY2FzZV93aGVuKEdhbXBsbjJhID09IDEgfiAiU2Vhc29uIFRpY2tldCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdhbXBsbjJiID09IDEgfiAiNSBNYXRjaCBQYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtcGxuMmMgPT0gMSB+ICIzIE1hdGNoIFBhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHYW1wbG4yZCA9PSAxIH4gIlNpbmdsZSBNYXRjaCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdhbXBsbjJlID09IDEgfiAiUGl0Y2hzaWRlIFRhYmxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR2FtcGxuMmYgPT0gMSB+ICJVbmRlY2lkZWQiKSwKICAgICAgICAgc2FsZXNfdGt0X3R5cGVfMjAxNyA9IGFzLmZhY3RvcihzYWxlc190a3RfdHlwZV8yMDE3KSwKICAgICAgICAgbWVkaWFfd2ViID0gY2FzZV93aGVuKE1lZGlhOF8xID09IDF8TWVkaWE4XzIgPT0gMXxNZWRpYThfMz09MXxNZWRpYThfND09MXxNZWRpYThfNT09MSB+ICJXZWJzaXRlIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZWRpYThfMSA9PSAyfE1lZGlhOF8yID09IDJ8TWVkaWE4XzM9PTJ8TWVkaWE4XzQ9PTJ8TWVkaWE4XzU9PTIgfiAiRmFjZWJvb2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNZWRpYThfMSA9PSAzfE1lZGlhOF8yID09IDN8TWVkaWE4XzM9PTN8TWVkaWE4XzQ9PTN8TWVkaWE4XzU9PTMgfiAiVHdpdHRlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1lZGlhOF8xID09IDR8TWVkaWE4XzIgPT0gNHxNZWRpYThfMz09NHxNZWRpYThfND09NHxNZWRpYThfNT09NCB+ICJJbnN0cmFncmFtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWVkaWE4XzEgPT0gNXxNZWRpYThfMiA9PSA1fE1lZGlhOF8zPT01fE1lZGlhOF80PT01fE1lZGlhOF81PT01IH4gIllvdXR1YmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5vdEF2YWlsYWJsZSIpLAogICAgICAgICBtZWRpYV93ZWIgPSBhcy5mYWN0b3IobWVkaWFfd2ViKSwKICAgICAgICAgbWVkaWFfc2Vhc29uX25ld3NwYXBlciA9IChNZWRpYTkpLAogICAgICAgICBtZWRpYV9zZWFzb25fdHYgPSAoTWVkaWExMCksCiAgICAgICAgIG1lZGlhX2FkczEgPSBjYXNlX3doZW4oc3RyX2RldGVjdChNZWRpYTEsIkhhcyBubyBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIk5vX2luZl9uZXdzcGFwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoTWVkaWExLCJIYXMgYSBwb3NpdGl2ZSBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIk5ld3NwYXBlcl9wb3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoTWVkaWExLCJIYWQgYSBuZWdhdGl2ZSBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIk5ld3NwYXBlcl9uZWciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiVW5rbm93biIpLAogICAgICAgICBtZWRpYV9hZHMzID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoTWVkaWEzLCJIYXMgbm8gaW5mbHVlbmNlIG9uIG15IGF0dGVuZGFuY2UiKSB+ICJOb19pbmZfRkNCaWxsYm9hcmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoTWVkaWEzLCJIYXMgYSBwb3NpdGl2ZSBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIkZDQmlsbGJvYXJkX3BvcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChNZWRpYTMsIkhhZCBhIG5lZ2F0aXZlIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiRkNCaWxsYm9hcmRfbmVnIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlVua25vd24iKSwKICAgICAgICAgbWVkaWFfYWRzNCA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KE1lZGlhNCwiSGFzIG5vIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiTm9faW5mbF9yYWRpbyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChNZWRpYTQsIkhhcyBhIHBvc2l0aXZlIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiUmFkaW9fcG9zaXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoTWVkaWE0LCJIYWQgYSBuZWdhdGl2ZSBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gIlJhZGlvX25lZ2F0aXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlVua25vd24iKSwKICAgICAgICAgbWVkaWFfYWRzNiA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KE1lZGlhNiwiSGFzIG5vIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiTm9faW5mbF9pbnRlcm5ldCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChNZWRpYTYsIkhhcyBhIHBvc2l0aXZlIGluZmx1ZW5jZSBvbiBteSBhdHRlbmRhbmNlIikgfiAiaW50ZXJuZXRfcG9zaXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoTWVkaWE2LCJIYWQgYSBuZWdhdGl2ZSBpbmZsdWVuY2Ugb24gbXkgYXR0ZW5kYW5jZSIpIH4gImludGVybmV0X25lZ2F0aXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlVua25vd24iKSwKICAgICAgICAgbWVkaWFfYWRzID0gY2FzZV93aGVuKG1lZGlhX2FkczEgPT0gIk5ld3NwYXBlcl9wb3MiIH4gIk5ld3NwYXBlcl9hZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFfYWRzMyA9PSAiRkNCaWxsYm9hcmRfcG9zIiB+ICJGQ0JpbGxib2FyZF9hZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFfYWRzNCA9PSAiUmFkaW9fcG9zaXRpdmUiIH4gIlJhZGlvX2FkcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpYV9hZHM2ID09ICJpbnRlcm5ldF9wb3NpdGl2ZSIgfiAiSW50ZXJuZXRfYWRzIgogICAgICAgICAgKSwKICAgICAgICAgbWVkaWFfYWRzID0gYXMuZmFjdG9yKG1lZGlhX2FkcyksCiAgICAgICAgIG1lZGlhX2FkczEgPSBhcy5mYWN0b3IobWVkaWFfYWRzMSksCiAgICAgICAgIG1lZGlhX2FkczMgPSBhcy5mYWN0b3IobWVkaWFfYWRzMyksCiAgICAgICAgIG1lZGlhX2FkczQgPSBhcy5mYWN0b3IobWVkaWFfYWRzNCksCiAgICAgICAgIG1lZGlhX2FkczYgPSBhcy5mYWN0b3IobWVkaWFfYWRzNiksCiAgICAgICAgIG1lcl9idXlfb25saW5lMSA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KEJ1eW9ubDEsIkFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlvbmwxLCJEaXNhZ3JlZSIpIH4gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQnV5b25sMSwiU29tZXdoYXQgZGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJ1eW9ubDEsIlNvbWV3aGF0IGFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlvbmwxLCJTdHJvbmdseSBhZ3JlZSIpIH4gIjEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQnV5b25sMSwiU3Ryb25nbHkgRGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIjAiKSwKICAgICAgICAgbWVyX2J1eV9vbmxpbmUxID0gYXMuZmFjdG9yKG1lcl9idXlfb25saW5lMSksCiAgICAgICAgIG1lcl9idXlfbWF0Y2gxID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoQnV5TWF0MSwiQWdyZWUiKSB+ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJ1eU1hdDEsIkRpc2FncmVlIikgfiAiMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlNYXQxLCJTb21ld2hhdCBkaXNhZ3JlZSIpIH4gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQnV5TWF0MSwiU29tZXdoYXQgYWdyZWUiKSB+ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJ1eU1hdDEsIlN0cm9uZ2x5IGFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlNYXQxLCJTdHJvbmdseSBEaXNhZ3JlZSIpIH4gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiMCIpLAogICAgICAgICBtZXJfYnV5X21hdGNoMSA9IGFzLmZhY3RvcihtZXJfYnV5X21hdGNoMSksCiAgICAgICAgIG1lcl9idXlfc3RvcmUxID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoQnV5U3RvcjEsIkFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlTdG9yMSwiRGlzYWdyZWUiKSB+ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJ1eVN0b3IxLCJTb21ld2hhdCBkaXNhZ3JlZSIpIH4gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQnV5U3RvcjEsIlNvbWV3aGF0IGFncmVlIikgfiAiMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChCdXlTdG9yMSwiU3Ryb25nbHkgYWdyZWUiKSB+ICIxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJ1eVN0b3IxLCJTdHJvbmdseSBEaXNhZ3JlZSIpIH4gIjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiMCIpLAogICAgICAgICBtZXJfYnV5X3N0b3JlMSA9IGFzLmZhY3RvcihtZXJfYnV5X3N0b3JlMSksCiAgICAgICAgIG1lcl9idXlfb25saW5lID0gY2FzZV93aGVuKG1lcl9idXlfb25saW5lMSA9PSAxIH4gIkJ1eV9PbmxpbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVyX2J1eV9vbmxpbmUxID09IDIgfiAiRG9Ob3RfQnV5X09ubGluZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJfYnV5X29ubGluZTEgPT0gMCB+ICJOZXV0cmFsIiksCiAgICAgICAgIG1lcl9idXlfbWF0Y2ggPSBjYXNlX3doZW4obWVyX2J1eV9tYXRjaDEgPT0gMSB+ICJCdXlfYXRNYXRjaCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJfYnV5X21hdGNoMSA9PSAyIH4gIkRvTm90X0J1eV9hdE1hdGNoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcl9idXlfbWF0Y2gxID09IDAgfiAiTmV1dHJhbCIpLAogICAgICAgICBtZXJfYnV5X3N0b3JlID0gY2FzZV93aGVuKG1lcl9idXlfc3RvcmUxID09IDEgfiAiQnV5X2F0U3RvcmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVyX2J1eV9zdG9yZTEgPT0gMiB+ICJEb05vdF9CdXlfYXRTdG9yZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJfYnV5X3N0b3JlMSA9PSAwIH4gIk5ldXRyYWwiKSwKICAgICAgICAgbWVyX2J1eV9vbmxpbmUgPSBhcy5mYWN0b3IobWVyX2J1eV9vbmxpbmUpLAogICAgICAgICBtZXJfYnV5X21hdGNoID0gYXMuZmFjdG9yKG1lcl9idXlfbWF0Y2gpLAogICAgICAgICBtZXJfYnV5X3N0b3JlID0gYXMuZmFjdG9yKG1lcl9idXlfc3RvcmUpLAogICAgICAgICBtZXJfYnV5X3ByZWYgPSBjYXNlX3doZW4obWVyX2J1eV9vbmxpbmUgPT0gIkJ1eV9PbmxpbmUiIH4gIk9ubGluZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lcl9idXlfbWF0Y2ggPT0gIkJ1eV9hdE1hdGNoIiB+ICJEdXJpbmcgTWF0Y2giLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJfYnV5X3N0b3JlID09ICJCdXlfYXRTdG9yZSIgfiAiQXQgU3RvcmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk5ldXRyYWwiKSwKICAgICAgICAgbWVyX2J1eV9wcmVmID0gYXMuZmFjdG9yKG1lcl9idXlfcHJlZiksCiAgICAgICAgIG1lcl9wdXJjaGFzZV9zcG9uc29ycyA9IGNhc2Vfd2hlbihQdXJjaHMxID09ICJZZXMiIH4gIkNhcnRlciBTdWJhcnUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQdXJjaHMyID09ICJZZXMiIH4gIk1pY3Jvc29mdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFB1cmNoczMgPT0gIlllcyIgfiAiUGVwc2kiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQdXJjaHM0ID09ICJZZXMiIH4gIkJFQ1UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQdXJjaHM5ID09ICJZZXMiIH4gIktyYWtlbiBDb25nZWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQdXJjaHMxMCA9PSAiWWVzIiB+ICJSdWZmbmVjayBTY2FydmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJOb3Qgc3VyZSIpLAogICAgICAgICBtZXJfcHVyY2hhc2Vfc3BvbnNvcnMgPSBhcy5mYWN0b3IobWVyX3B1cmNoYXNlX3Nwb25zb3JzKSwKICAgICAgICAgbWVyX3JlaWduID0gY2FzZV93aGVuKFNoaXJ0MSA9PSAxIH4gIlNob3J0X1NsZWV2ZV9TaGlydCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaGlydDIgPT0gMSB+ICJMb25nX1NsZWV2ZV9TaGlydCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNoaXJ0MyA9PSAxIH4gIkphY2tldHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaGlydDQgPT0gMSB+ICJBY2Nlc3NvcmllcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTm8gcHJlZmVyZW5jZXMiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIG1lcl9yZWlnbiA9IGFzLmZhY3RvcihtZXJfcmVpZ24pLAogICAgICAgICBkZW1fZ2VuZGVyID0gYXMuZmFjdG9yKEdlbmRlciksCiAgICAgICAgIGRlbV9zZXh1YWxPcmllbnQgPSBhcy5mYWN0b3IoU2V4T3JpZW50KSwKICAgICAgICAgZGVtX3JhY2UgPSBhcy5mYWN0b3IoUmFjZSksCiAgICAgICAgIGF0dF9zZWFFdmVudCA9IGNhc2Vfd2hlbihTZWFFdm50MSA9PSAxIH4gIlNlYXR0bGUgU3Rvcm0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZWFFdm50MiA9PSAxIH4gIlNlYXR0bGUgU2VhaGF3a3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZWFFdm50MyA9PSAxIH4gIlNlYXR0bGUgU291bmRlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZWFFdm50NCA9PSAxIH4gIlNlYXR0bGUgTWFyaW5lcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTZWFFdm50NiA9PSAxIH4gIlNvdW5kZXJzIFdvbWVuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2VhRXZudDcgPT0gMSB+ICJTZWF0dGxlIE1hamVzdGljcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlYUV2bnQ4ID09IDEgfiAiVGFjb21hIFN0YXJzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2VhRXZudDkgPT0gMSB+ICJSYXQgQ2l0eSBSb2xsZXJnaXJscyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTm9BbnN3ZXIiKSwKICAgICAgICAgYXR0X3NlYUV2ZW50ID0gYXMuZmFjdG9yKGF0dF9zZWFFdmVudCksCiAgICAgICAgIGRlbV9tYXJpdGFsX3N0YXR1cyA9IChNYXJpdGFsKSwKICAgICAgICAgZGVtX2VkdWNhdGlvbiA9IChFZHVjYXQpLAogICAgICAgICBzYXRfcHJpY2VfZm9vZCA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KENvbnNhdDQsIlZlcnkgU2F0aXNmaWVkIikgfiAiUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb25zYXQ0LCJWZXJ5IERpc3NhdGlzZmllZCIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTiIpLAogICAgICAgICBzYXRfcXVhbGl0eSA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KENvbnNhdDEsIlZlcnkgU2F0aXNmaWVkIikgfiAiUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb25zYXQxLCJWZXJ5IERpc3NhdGlzZmllZCIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTiIpLAogICAgICAgICBzYXRfdmFyaWV0eSA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KENvbnNhdDIsIlZlcnkgU2F0aXNmaWVkIikgfiAiUyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb25zYXQyLCJWZXJ5IERpc3NhdGlzZmllZCIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTiIpLAogICAgICAgICBzYXRfcHJpY2VfZHJpbmsgPSBjYXNlX3doZW4oc3RyX2RldGVjdChDb25zYXQ1LCJWZXJ5IFNhdGlzZmllZCIpIH4gIlMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQ29uc2F0NSwiVmVyeSBEaXNzYXRpc2ZpZWQiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk4iKSwKICAgICAgICAgc2F0X2JlZXIgPSBjYXNlX3doZW4oc3RyX2RldGVjdChCZWVyc2F0MSwiVmVyeSBTYXRpc2ZpZWQiKSB+ICJTIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KEJlZXJzYXQxLCJWZXJ5IERpc3NhdGlzZmllZCIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTiIpLAogICAgICAgICBzYXRfZ2FtZWRheSA9IGNhc2Vfd2hlbihzYXRfcHJpY2VfZm9vZCA9PSAiUyIgfiAiU2F0aXNmYWN0b3J5IGZvb2QgcHJpY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdF9xdWFsaXR5ID09ICJTIiB+ICJTYXRpc2ZhY3RvcnkgcXVhbGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X3ByaWNlX2RyaW5rID09ICJTIiB+ICJTYXRpc2ZhY3RvcnkgZHJpbmsgcHJpY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdF92YXJpZXR5ID09ICJTIiB+ICJTYXRpc2ZpZWQgd2l0aCB2YXJpZXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfYmVlciA9PSAiUyIgfiAiU2F0aXNmYWN0b3J5IGJlZXIgc2VydmljZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X3ByaWNlX2Zvb2QgPT0gIkQiIH4gIkRpc3NhdGlzZnlpbmcgZm9vZCBwcmljZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X3F1YWxpdHkgPT0gIkQiIH4gIkRpc3NhdGlzZnlpbmcgcXVhbGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X3ByaWNlX2RyaW5rID09ICJEIiB+ICJEaXNzYXRpc2Z5aW5nIGRyaW5rIHByaWNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfdmFyaWV0eSA9PSAiRCIgfiAiRGlzc2F0aXNmaWVkIHdpdGggdmFyaWV0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X2JlZXIgPT0gIkQiIH4gIkRpc3NhdGlzZnlpbmcgYmVlciBzZXJ2aWNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJOZXV0cmFsIiksCiAgICAgICAgIGNvc3QxID0gY2FzZV93aGVuKHN0cl9kZXRlY3QoQ29zdDMsIkFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb3N0MywiRGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KENvc3QzLCJTb21ld2hhdCBkaXNhZ3JlZSIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQ29zdDMsIlNvbWV3aGF0IGFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb3N0MywiU3Ryb25nbHkgYWdyZWUiKSB+ICJBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KENvc3QzLCJTdHJvbmdseSBEaXNhZ3JlZSIpIH4gIkQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTiIpLAogICAgICAgICBjb3N0ID0gaWZfZWxzZShjb3N0MSA9PSAiQSIsICJDb3N0bHkiLCAiTm90IENvc3RseSIpLAogICAgICAgICBjb3N0ID0gYXMuZmFjdG9yKGNvc3QpLAogICAgICAgICBzYXRfZ2FtZWRheSA9IGFzLmZhY3RvcihzYXRfZ2FtZWRheSksCiAgICAgICAgIHNhdF9za2lsbCA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KFNraWxsMiwiQWdyZWUiKSB+ICJBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFNraWxsMiwiRGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFNraWxsMiwiU29tZXdoYXQgZGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFNraWxsMiwiU29tZXdoYXQgYWdyZWUiKSB+ICJBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFNraWxsMiwiU3Ryb25nbHkgYWdyZWUiKSB+ICJBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFNraWxsMiwiU3Ryb25nbHkgRGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk4iKSwgCiAgICAgICAgICBzYXRfc3VjY2VzcyA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KFN1Y2Nlc3MyLCJBZ3JlZSIpIH4gIkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoU3VjY2VzczIsIkRpc2FncmVlIikgfiAiRCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChTdWNjZXNzMiwiU29tZXdoYXQgZGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFN1Y2Nlc3MyLCJTb21ld2hhdCBhZ3JlZSIpIH4gIkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoU3VjY2VzczIsIlN0cm9uZ2x5IGFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChTdWNjZXNzMiwiU3Ryb25nbHkgRGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk4iKSwgCiAgICAgICAgICBzYXRfZHJhbWEgPSBjYXNlX3doZW4oc3RyX2RldGVjdChEcmFtYTQsIkFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChEcmFtYTQsIkRpc2FncmVlIikgfiAiRCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChEcmFtYTQsIlNvbWV3aGF0IGRpc2FncmVlIikgfiAiRCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChEcmFtYTQsIlNvbWV3aGF0IGFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChEcmFtYTQsIlN0cm9uZ2x5IGFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChEcmFtYTQsIlN0cm9uZ2x5IERpc2FncmVlIikgfiAiRCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJOIiksCiAgICAgICAgICBzYXRfY29zdCA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KENvc3QzLCJBZ3JlZSIpIH4gIkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQ29zdDMsIkRpc2FncmVlIikgfiAiRCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb3N0MywiU29tZXdoYXQgZGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KENvc3QzLCJTb21ld2hhdCBhZ3JlZSIpIH4gIkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QoQ29zdDMsIlN0cm9uZ2x5IGFncmVlIikgfiAiQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChDb3N0MywiU3Ryb25nbHkgRGlzYWdyZWUiKSB+ICJEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk4iKSwKICAgICAgICAgIHNhdGlzZmFjbl9wZXJmID0gY2FzZV93aGVuKHNhdF9za2lsbCA9PSAiQSIgfiAiU2F0aXNmaWVkX3dpdGhfc2tpbGwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdF9zdWNjZXNzID09ICJBIiB+ICJTYXRpc2ZpZWRfd2l0aF9zdWNjZXNzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfZHJhbWEgPT0gIkEiIH4gIlNhdGlzZmllZF93aXRoX2RyYW1hIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfY29zdCA9PSAiQSIgfiAiU2F0aXNmaWVkX3dpdGhfY29zdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X3NraWxsID09ICJEIiB+ICJOb3QgU2F0aXNmaWVkX3NraWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfc3VjY2VzcyA9PSAiRCIgfiAiVE5vdCBTYXRpc2ZpZWRfc3VjY2VzcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0X2RyYW1hID09ICJEIiB+ICJOb3QgU2F0aXNmaWVkX2RyYW1hIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXRfY29zdCA9PSAiRCIgfiAiTm90IFNhdGlzZmllZF9jb3N0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJOb3QgU2F0aXNmaWVkIiksCiAgICAgICAgICBzYXRpc2ZhY25fcGVyZiA9IGFzLmZhY3RvcihzYXRpc2ZhY25fcGVyZikKICAgICAgICAgIAogIAogICAgICAgICAgICkgJT4lCiAgZmlsdGVyKGF0dF9kaXN0YW5jZSAhPSAiTkEiKSAlPiUKICBmaWx0ZXIoc2FsZXNfbnVtb2ZtYXRjaF8yMDE3ICE9ICJOQSIpICAlPiUgCiAgZmlsdGVyKG1lZGlhX3NlYXNvbl90diAhPSAiTkEiKSAlPiUKICBmaWx0ZXIobWVkaWFfc2Vhc29uX25ld3NwYXBlciAhPSAiTkEiKSAlPiUKICAjZmlsdGVyKG1lZGlhX2FkcyE9ICJOQSIpICAlPiUKICBmaWx0ZXIoU3BuZGxzdFMgIT0gIk5BIikgJT4lCiAgZmlsdGVyKFNwbmRsc3RPICE9ICJOQSIpICU+JQogIHJlbmFtZShzYWxlc19leHBfc2VsZjIwMTYgPSBTcG5kbHN0UywgCiAgICAgICAgIHNhbGVzX2V4cF9vdGgyMDE2ID0gU3BuZGxzdE8pICU+JQogIHNlbGVjdChmYWN0b3IxX2F0dGVuZCxhdHRfZmlyc3RfYXR0ZW5kLGF0dF9pbnRlcmVzdCxhdHRfZ2FtZXdpdGgsYXR0X3RyYXZlbF9tb2RlLGF0dF9kaXN0YW5jZSwKICAgICAgICAgYXR0X3Byb21vX2VmZmVjdCxhdHRfcGxheWVyX2ZhbixhdHRfc2VhRXZlbnQsIGF0dF9tb3N0X3ByZWZfdGltZSwKICAgICAgICAgYXR0X2xlYXN0X3ByZWZlcnJlZF90aW1pbmcsYXR0X2F0dGVuZF8yMDE3LGF0dF9hdHRlbmRfMjAxNiwgYXR0X2dhbWV3aXRoLAogICAgICAgICBzYWxlc190aWNrZXRfdHlwZSwgc2FsZXNfZXhwX3NlbGYyMDE2LCAKICAgICAgICAgc2FsZXNfZXhwX290aDIwMTYsc2FsZXNfbnVtb2ZtYXRjaF8yMDE3LHNhbGVzX3RrdF90eXBlXzIwMTcsbWVkaWFfd2ViLAogICAgICAgICBtZWRpYV9zZWFzb25fbmV3c3BhcGVyLG1lZGlhX3NlYXNvbl90diwKICAgICAgICAgbWVyX2J1eV9wcmVmLGNvc3QsCiAgICAgICAgIG1lcl9wdXJjaGFzZV9zcG9uc29ycyxtZXJfcmVpZ24sZGVtX2dlbmRlcixkZW1fc2V4dWFsT3JpZW50LGRlbV9tYXJpdGFsX3N0YXR1cywKICAgICAgICAgZGVtX2VkdWNhdGlvbixzYXRfZ2FtZWRheSxzYXRpc2ZhY25fcGVyZikgICU+JQogIGRyb3BfbmEoKQoKI0V4YW1pbmUgdGhlIGZpcnN0IDEwIG9ic2VydmF0aW9ucyB0byBtYWtlIHN1cmUgZGF0YSBzZXQgbG9va3Mgb2sKI2hlYWQoc2VhdHRsZV9yZWlnbiwxMCkKCiMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcwojc3VtbWFyeShzZWF0dGxlX3JlaWduKQoKIyBSZXZpZXcgZGF0YSBzdHJ1Y3R1cmVzCiNzdHIoc2VhdHRsZV9yZWlnbikKCiMgVGhlIHBhbGV0dGUgd2l0aCBncmV5OgpjYlBhbGV0dGUgPC0gYygiI0U2OUYwMCIsICIjNTZCNEU5IiwgIiMwMDlFNzMiLCAiI0YwRTQ0MiIsICIjMDA3MkIyIiwgIiNENTVFMDAiLCAiI0NDNzlBNyIpCgpgYGAKCiMjIyMjT2JzZXJ2YXRpb25zCgotIERhdGEgZm9yIHRoZSBTZWF0dGxlIFJlaWduIEZDIFNvY2NlciBUZWFtCi0gNDE2IG9ic2VydmF0aW9ucyBvZiAyMyB2YXJpYWJsZXMgCi0gMTcgRmFjdG9yIFZhcmlhYmxlcwotIDUgSW50ZWdlciBWYXJpYWJsZQotIDEgTnVtZXJpYyBWYXJpYWJsZXMKClNlbGVjdGluZyByZWxldmFudCBjb2x1bW5zICAKPT09PT09PT09PT09PT09PT09PT09PT09PT09CgpgYGB7cn0KIyBTZWxlY3QgcmVxdWlyZWQgY29sdW1ucyBmcm9tIHJhdyBkYXRhCnNlYV9yZWlnbl9kYXRhIDwtIHNlYXR0bGVfcmVpZ24gJT4lCiAgIHNlbGVjdChhdHRfZmlyc3RfYXR0ZW5kLGF0dF9pbnRlcmVzdCxhdHRfZGlzdGFuY2UsCiAgICAgICAgIGF0dF9wcm9tb19lZmZlY3QsYXR0X3NlYUV2ZW50LCBhdHRfbW9zdF9wcmVmX3RpbWUsCiAgICAgICAgIGF0dF9hdHRlbmRfMjAxNyxhdHRfYXR0ZW5kXzIwMTYsYXR0X2dhbWV3aXRoLAogICAgICAgICBzYWxlc190aWNrZXRfdHlwZSwgc2FsZXNfZXhwX3NlbGYyMDE2LCAKICAgICAgICAgc2FsZXNfZXhwX290aDIwMTYsc2FsZXNfbnVtb2ZtYXRjaF8yMDE3LHNhbGVzX3RrdF90eXBlXzIwMTcsCiAgICAgICAgIG1lZGlhX3dlYixjb3N0LAogICAgICAgICBtZWRpYV9zZWFzb25fbmV3c3BhcGVyLG1lZGlhX3NlYXNvbl90diwKICAgICAgICAgbWVyX2J1eV9wcmVmLAogICAgICAgICBtZXJfcHVyY2hhc2Vfc3BvbnNvcnMsbWVyX3JlaWduLGRlbV9nZW5kZXIsZGVtX3NleHVhbE9yaWVudCxkZW1fbWFyaXRhbF9zdGF0dXMsCiAgICAgICAgIGRlbV9lZHVjYXRpb24sc2F0X2dhbWVkYXksc2F0aXNmYWNuX3BlcmYpCgoKc3VtbWFyeShzZWFfcmVpZ25fZGF0YSkKYGBgCgoqQXNrIHF1ZXN0aW9ucyB0byBmb2xsb3cgdXAgb24gaW4gZGV0YWlsZWQgRURBKiAgCjEuIEhvdyBkbyB0aGUgYXR0ZW5kYW5jZSB2YXJ5IHdoZW4gcGVvcGxlIHRyYXZlbGxlZCBsb25nZXIgZGlzdGFuY2UgdG8gd2F0Y2ggdGhlIG1hdGNoPyAgCjIuIEhvdyBkbyB0aGUgYXR0ZW5kYW5jZSB2YXJ5IHdoZW4gcGVvcGxlIGF0dGVuZGVkIGEgcHJldmlvdXMgbWF0Y2ggYW5kIHdoZW4gdGhleSBoYXZlIG5vdD8gIAozLiBIb3cgZG9lcyBtZWRpYSBzdWNoIGFzIHdlYnNpdGUsIGZhY2Vib29rIGVmZmVjdCB0aGUgbnVtYmVyIG9mIHBlb3BsZSB3aG8gYXJlIGxpa2VseSB0byBhdHRlbmQgYSBtYXRjaCBpbiAyMDE3Pwo0LiBXaGF0IGlzIHRoZSBwdXJjaGFzaW5nIGhhYml0cyBvZiBwZW9wbGUgd2hvIGhhdmUgYXR0ZW5kZWQgcHJldmlvdXMgbWF0Y2hlcz8KNS4gSG93IGlzIHRoZSBvdmVyYWxsIGdhbWUgZGF5IGV4cGVyaWVuY2Ugb2YgcGVvcGxlIHdobyBoYXZlIGF0dGVuZGVkIHRoZSBtYXRjaGVzIGluIHBhc3Q/CjYuIFdoYXQgaXMgdGhlIGltcGFjdCBvZiBzcG9uc29ycyBpbiBzZWxsaW5nIHRoZSBtZXJjaGFuZGlzZSBhdCBzdG9yZSB2cyBvbmxpbmUgdnMgZHVyaW5nIG1hdGNoPwoKIAoKCmBgYHtyfQojIFNlbGVjdGluZyByZWxldmFudCBjb2x1bW5zIGZvciBmbGV4ZGFzaGJvYXJkCgpzZWFfZmxleGRhc2ggPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgIHNlbGVjdChhdHRfcHJvbW9fZWZmZWN0LCBhdHRfbW9zdF9wcmVmX3RpbWUsc2FsZXNfZXhwX3NlbGYyMDE2LCBhdHRfYXR0ZW5kXzIwMTYsCiAgICAgICAgIHNhbGVzX2V4cF9vdGgyMDE2LHNhbGVzX251bW9mbWF0Y2hfMjAxNyxzYWxlc190a3RfdHlwZV8yMDE3LG1lcl9idXlfcHJlZiwKICAgICAgICAgYXR0X2F0dGVuZF8yMDE3LCBtZXJfcmVpZ24sZGVtX2dlbmRlcixkZW1fZWR1Y2F0aW9uKQoKd3JpdGUuY3N2KHNlYV9mbGV4ZGFzaCwgIi9Vc2Vycy9Mb3ZlSG9udS9Eb2N1bWVudHMvV2ludGVyMjAxOS9CVUFONTIxMC1WaXN1YWxpemF0aW9uL3NlYV9mbGV4ZGFzaC5jc3YiKQogCnN1bW1hcnkoc2VhX2ZsZXhkYXNoKQpgYGAKCjEuIFVuaXZhcmlhdGUgbm9uLWdyYXBoaWNhbCAtIENhdGVnb3JpY2FsIAo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKLSBDYXRlZ29yaWNhbCBkYXRhIC0gdGFidWxhdGlvbgoKI0ZhY3RvcjEgQXR0ZW5kYW5jZQoKIyNBdHRlbmRhbmNlX1Bhc3RfWWVhcnMKCmBgYHtyfQoKYXR0ZW5kYW5jZV9maXJzdCA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgICMgJT4lIFBpcGVzIGRhdGEgdG8gZ3JvdXBfYnkoKSBmdW5jdGlvbgogIGdyb3VwX2J5KGF0dF9maXJzdF9hdHRlbmQpICU+JSAgICAgICAgICAgIyBncm91cF9ieSgpIG9yZ2FuaXNlcyBkYXRhIGJ5IHJlZ2lvbgogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAgICAgICAgICAgICAgICAgICAjIGNvdW50IGlzIHRoZSBuZXcgdmFyaWFibGUgbmFtZSwgbigpIGlzIGEgY291bnRpbmcgZnVuY3Rpb24KICAgICAgcGVyY2VudCA9IChzdW0oY291bnQpIC8gbnJvdyhzZWFfcmVpZ25fZGF0YSkpICogMTAwLCAjIHBlcmNlbnQgaXMgYSBuZXcgdmFyaWFibGUsIHN1bSgpIGFuZCBucm93KCkgYXJlIGZ1bmN0aW9ucwogICAgICBhdmdfZGlzdGFuY2UgPSBtZWFuKGF0dF9kaXN0YW5jZSkpICAgICAgICAgICAgICMgbWVhbiBkaXN0YW5jZSB0cmF2ZWxsZWQKYXR0ZW5kYW5jZV9maXJzdApgYGAKCi0gMjAxMyBhdHRlbmRhbmNlIGlzIGhpZ2hlc3QKCiMjQXR0ZW5kYW5jZV9JbnRlcmVzdCAKCmBgYHtyfQoKYXR0ZW5kYW5jZV9pbnRlcmVzdCA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgZ3JvdXBfYnkoYXR0X2ludGVyZXN0KSAlPiUgICAgICAgICAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICBwZXJjZW50ID0gKHN1bShjb3VudCkgLyBucm93KHNlYV9yZWlnbl9kYXRhKSkgKiAxMDAsICMgcGVyY2VudCBpcyBhIG5ldyB2YXJpYWJsZSwgc3VtKCkgYW5kIG5yb3coKSBhcmUgZnVuY3Rpb25zCiAgICAgIGF2Z19kaXN0YW5jZSA9IG1lYW4oYXR0X2Rpc3RhbmNlKSkgICAgICAgICAgICAgICAgICAgICAgICAjIG1lYW4gZGlzdGFuY2UgdHJhdmVsbGVkCmF0dGVuZGFuY2VfaW50ZXJlc3QKYGBgCgojI0F0dGVuZGFuY2VfTG9jYWxfRXZlbnQKCmBgYHtyfQoKIyBncm91cF9ieSgpIGJyYW5kIG5hbWUKYXR0ZW5kYW5jZV9sb2NhbF9ldmVudCA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgZ3JvdXBfYnkoYXR0X3NlYUV2ZW50KSAlPiUgICAgICAgICAgICMgZ3JvdXBfYnkoKSBvcmdhbmlzZXMgZGF0YSBieSBwcm9kdWNlcgogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAgCiAgICAgIHBlcmNlbnQgPSAoc3VtKGNvdW50KSAvIG5yb3coc2VhX3JlaWduX2RhdGEpKSAqIDEwMCwgIyBwZXJjZW50IGlzIGEgbmV3IHZhcmlhYmxlLCBzdW0oKSBhbmQgbnJvdygpIGFyZSBmdW5jdGlvbnMKICAgICAgYXZnX2Rpc3RhbmNlID0gbWVhbihhdHRfZGlzdGFuY2UpKSAgICAgICAgICAgICAgICAgICAgICAgICMgbWVhbiBkaXN0YW5jZSB0cmF2ZWxsZWQKYXR0ZW5kYW5jZV9sb2NhbF9ldmVudApgYGAKCiMjQXR0ZW5kYW5jZV9Qcm9tb19FZmZlY3QKCmBgYHtyfQojIGdyb3VwX2J5KCkgYWQKYXR0ZW5kYW5jZV9wcm9tb19lZmZlY3QgPC0gc2VhX3JlaWduX2RhdGEgJT4lIAogIGdyb3VwX2J5KGF0dF9wcm9tb19lZmZlY3QpICU+JSAgICAgICAgICAgIyBncm91cF9ieSgpIG9yZ2FuaXNlcyBkYXRhIGJ5IHByb2R1Y2VyCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCAgICAgICAgCiAgICAgIHBlcmNlbnQgPSAoc3VtKGNvdW50KSAvIG5yb3coc2VhX3JlaWduX2RhdGEpKSAqIDEwMCwgIyBwZXJjZW50IGlzIGEgbmV3IHZhcmlhYmxlLCBzdW0oKSBhbmQgbnJvdygpIGFyZSBmdW5jdGlvbnMKICAgICAgYXZnX2Rpc3RhbmNlID0gbWVhbihhdHRfZGlzdGFuY2UpKSAgICAgICAgICAgICAgICAgICAgICAgICMgbWVhbiBkaXN0YW5jZSB0cmF2ZWxsZWQKYXR0ZW5kYW5jZV9wcm9tb19lZmZlY3QKYGBgCgojI0F0dGVuZGFuY2VfMjAxNyAKCmBgYHtyfQoKIyBncm91cF9ieSgpIGFkCmF0dGVuZGFuY2VfMjAxNyA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgZ3JvdXBfYnkoYXR0X2F0dGVuZF8yMDE3KSAlPiUgICAgICAgICAgIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAKICAgICAgcGVyY2VudCA9IChzdW0oY291bnQpIC8gbnJvdyhzZWFfcmVpZ25fZGF0YSkpICogMTAwLAogICAgICBhdmdfZGlzdGFuY2UgPSBtZWFuKGF0dF9kaXN0YW5jZSkpICAgICAgICAgICAgICAgICAgICAgIAphdHRlbmRhbmNlXzIwMTcKYGBgCgoKIyNBdHRlbmRhbmNlX1ByZWZfVGltaW5nIAoKYGBge3J9CiMgZ3JvdXBfYnkoKSBhZAphdHRlbmRhbmNlX3RpbWluZyA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgIAogIGdyb3VwX2J5KGF0dF9tb3N0X3ByZWZfdGltZSkgJT4lICAgICAgICAgIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAgIAogICAgICBwZXJjZW50ID0gKHN1bShjb3VudCkgLyBucm93KHNlYV9yZWlnbl9kYXRhKSkgKiAxMDAsIAogICAgICBhdmdfZGlzdGFuY2UgPSBtZWFuKGF0dF9kaXN0YW5jZSkpICAgICAgICAgICAgICAgICAgICAgICAKYXR0ZW5kYW5jZV90aW1pbmcKYGBgCgojRmFjdG9yMi1TYWxlcwoKIyNTYWxlc19UaWNrZXRfVHlwZQoKYGBge3J9CgpzYWxlc190aWNrZXRfdHlwZSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgIAogIGdyb3VwX2J5KHNhbGVzX3RpY2tldF90eXBlKSAlPiUgICAgICAgICAgICMgZ3JvdXBfYnkoKSBvcmdhbmlzZXMgZGF0YSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksICAgICAgICAKICAgICAgcGVyY2VudCA9IChzdW0oY291bnQpIC8gbnJvdyhzZWFfcmVpZ25fZGF0YSkpICogMTAwLCAKICAgICAgIGF2Z19leHBfc2VsZiA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSwgICAgICAgICAgICAgICAgICAgICAgICAjIG1lYW4gZGlzdGFuY2UgdHJhdmVsbGVkCiAgICAgICBhdmdfZXhwX290aGVycyA9IG1lYW4oc2FsZXNfZXhwX290aDIwMTYpKSAgICAgICAgICAgICAgICAgICAgICAgICMgbWVhbiBkaXN0YW5jZSB0cmF2ZWxsZWQKICAgICAgIyBjb3VudF9tYXRjaF8yMDE2ID0gc3VtKGF0dF9maXJzdF9hdHRlbmRfMjAxNikpICAgICAgICAgICAgICAgICAgICAgICAgIyBtZWFuIGRpc3RhbmNlIHRyYXZlbGxlZApzYWxlc190aWNrZXRfdHlwZQpgYGAKCmBgYHtyfQoKc2FsZXNfdGlja2V0X3R5cGVfMjAxNyA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgIAogIGdyb3VwX2J5KHNhbGVzX3RrdF90eXBlXzIwMTcpICU+JSAgICAgICAgICAgIyBncm91cF9ieSgpIG9yZ2FuaXNlcyBkYXRhIGJ5IHRpY2tldCB0eXBlCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCAgICAgICAgCiAgICAgIHBlcmNlbnQgPSAoc3VtKGNvdW50KSAvIG5yb3coc2VhX3JlaWduX2RhdGEpKSAqIDEwMCwgCiAgICAgICBhdmdfZXhwX3NlbGYgPSBtZWFuKHNhbGVzX2V4cF9zZWxmMjAxNiksICAgICAgICAgICAgICAgICAgICAgCiAgICAgICBhdmdfZXhwX290aGVycyA9IG1lYW4oc2FsZXNfZXhwX290aDIwMTYpLCAgICAjIG1lYW4gZXhwZW5kaXR1cmUKICAgICAgIG51bWJlcm9mbWF0Y2hfMjAxNyA9IHN1bShzYWxlc19udW1vZm1hdGNoXzIwMTcpKSAgICMgbWVhbiBvZiBudW0gb2YgbWF0Y2hlcwpzYWxlc190aWNrZXRfdHlwZV8yMDE3CmBgYAoKCiMjTWVkaWFfV2ViCgpgYGB7cn0KCm1lZGlhX3dlYiA8LSBzZWFfcmVpZ25fZGF0YSAlPiUgIAogIGdyb3VwX2J5KG1lZGlhX3dlYikgJT4lICAgICAgICAgICAjIGdyb3VwX2J5KCkgb3JnYW5pc2VzIGRhdGEgYnkgd2ViIG1lZGlhIHVzZWQKICBzdW1tYXJpc2UoY291bnQgPSBuKCksICAgICAgICAKICAgICAgcGVyY2VudCA9IChzdW0oY291bnQpIC8gbnJvdyhzZWFfcmVpZ25fZGF0YSkpICogMTAwLCAKICAgICAgIG51bWJlcm9mbWF0Y2hfMjAxNyA9IHN1bShzYWxlc19udW1vZm1hdGNoXzIwMTcpKSAgICAgICAgICAgICAgICAgICAgICAgICMgbWVhbiBvZiBudW0gb2YgbWF0Y2hlcwptZWRpYV93ZWIKYGBgCgojI01lcmNoYW5kaXNlX1B1cmNoYXNlX1Nwb25zb3JzCgpgYGB7cn0KCm1lcmNoYW5kaXNlX3Nwb25zb3JzIDwtIHNlYV9yZWlnbl9kYXRhICU+JSAgCiAgZ3JvdXBfYnkobWVyX3B1cmNoYXNlX3Nwb25zb3JzKSAlPiUgICAgICAgICAgICMgZ3JvdXBfYnkoKSBvcmdhbmlzZXMgZGF0YSBieSB3ZWIgbWVkaWEgdXNlZAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAgIAogICAgICBwZXJjZW50ID0gKHN1bShjb3VudCkgLyBucm93KHNlYV9yZWlnbl9kYXRhKSkgKiAxMDAsIAogICAgICAgbnVtYmVyb2ZtYXRjaF8yMDE3ID0gc3VtKHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICAgICAgICAgICAgICAgICAgICAgICAgIyBtZWFuIG9mIG51bSBvZiBtYXRjaGVzCm1lcmNoYW5kaXNlX3Nwb25zb3JzCmBgYAoKIyNNZXJjaGFuZGlzZV9SZWlnbkZDCgpgYGB7cn0KCm1lcmNoYW5kaXNlX3JlaWduIDwtIHNlYV9yZWlnbl9kYXRhICU+JSAgCiAgZ3JvdXBfYnkobWVyX3JlaWduKSAlPiUgICAgICAgICAgICMgZ3JvdXBfYnkoKSBvcmdhbmlzZXMgZGF0YSBieSB3ZWIgbWVkaWEgdXNlZAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgICAgICAgIAogICAgICBwZXJjZW50ID0gKHN1bShjb3VudCkgLyBucm93KHNlYV9yZWlnbl9kYXRhKSkgKiAxMDAsIAogICAgICAgbnVtYmVyb2ZtYXRjaF8yMDE3ID0gc3VtKHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICAgICAgICAgICAgICAgICAgICAgICAgIyBtZWFuIG9mIG51bSBvZiBtYXRjaGVzCm1lcmNoYW5kaXNlX3JlaWduCmBgYAoKMi4gVW5pdmFyaWF0ZSBncmFwaGljYWwgIC0gQ2F0ZWdvcmljYWwKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMjQXR0ZW5kYW5jZSBwYXN0IHllYXJzIFNlYXR0bGUgRkMgUmVpZ24gbWF0Y2gKCgpgYGB7cn0KIyBDb2RlIGhpc3RvZ3JhbXMgdXNpbmcgZ3JpZC5hcnJhbmdlIHRvIHNlZSBxdWFudCB2YXJpYWJsZXMgdG9nZXRoZXIgZ3JvdXAgYnkgd2hlbiBmaXJzdCBhdHRlbmRlZCBhIFNlYXR0bGUgUmVpZ24gRkMgbWF0Y2gKZ3JpZC5hcnJhbmdlKAogIAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF0dF9maXJzdF9hdHRlbmQsIHkgPSBhdHRfZGlzdGFuY2UpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGNvb3JkX2ZsaXAoKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdHRfZmlyc3RfYXR0ZW5kLCB5ID0gbWVkaWFfc2Vhc29uX25ld3NwYXBlcikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF0dF9maXJzdF9hdHRlbmQsIHkgPSBtZWRpYV9zZWFzb25fdHYpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGNvb3JkX2ZsaXAoKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdHRfZmlyc3RfYXR0ZW5kLCB5ID0gc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCiAgbmNvbCA9IDIKKQpgYGAKCi0gUGVvcGxlIHdobyBmaXJzdCBhdHRlbmRlZCBhIFNlYXR0bGUgUmVpZ24gRkMgbWF0Y2gsIHRyYXZlbGxlZCBtYXhpbXVtIGRpc3RhbmNlIG9mIDIwMDAgbWlsZXMgaW4gMjAxNSwgZGVjbGluZWQgaW4gMjAxNgotIEluIDIwMTMsIGFwcHJveGltYXRlbHkgMTgwIHRpbWVzIHBlciB3ZWVrIGR1cmluZyB0aGUgc2Vhc29uIHBlb3BsZSByZWFkIGFib3V0IHRoZSBSZWlnbiBpbiB0aGUgbmV3c3BhcGVyIHdobyBhdHRlbmRlZCBtYXRjaCAKLSBJbiAyMDE1LCBhcHByb3hpbWF0ZWx5IDI4MCB0aW1lcyBkdXJpbmcgdGhlIHNlYXNvbiBwZW9wbGUgd2F0Y2ggdGhlIFJlaWduIG9uIFRWIHdobyBhdHRlbmRlZCBtYXRjaCwgb25seSA2MCB0aW1lcyBpbiAyMDE2Ci0gUGVvcGxlIHdobyBoYXZlIGF0dGVuZGVkIGEgMjAxNiBtYXRjaCwgYXJlIGxlYXN0IGxpa2VseSB0byBhdHRlbmQgYSBtYXRjaCBpbiAyMDE3CgojI0F0dGVuZGFuY2UgbG9jYWwgZXZlbnQKCgpgYGB7cn0KIyBDb2RlIGhpc3RvZ3JhbXMgdXNpbmcgZ3JpZC5hcnJhbmdlIHNvIGNhbiBzZWUgYWxsIHF1YW50IHZhcmlhYmxlcyB0b2dldGhlciBncm91cCBieSBsb2NhbCBldmVudHMgYXR0ZW5kYW5jZQpncmlkLmFycmFuZ2UoCiAgCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXR0X3NlYUV2ZW50LCB5ID0gYXR0X2Rpc3RhbmNlKSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXR0X3NlYUV2ZW50LCB5ID0gbWVkaWFfc2Vhc29uX25ld3NwYXBlcikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF0dF9zZWFFdmVudCwgeSA9IG1lZGlhX3NlYXNvbl90dikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF0dF9zZWFFdmVudCwgeSA9IHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIG5jb2wgPSAyCikKYGBgCgotIFBlb3BsZSB3aG8gZm9sbG93IFNlYXR0bGUgU291bmRlcnMsIGFyZSBtb3JlIGxpa2VseSB0byBhdHRlbmQgdGhlIFNlYXR0bGUgUmVpZ24gRkMgbWF0Y2ggaW4gMjAxNwoKIyNBdHRlbmRhbmNlIHByZWZlcnJlZCB0aW1pbmdzCgoKYGBge3J9CiMgQ29kZSBoaXN0b2dyYW1zIHVzaW5nIGdyaWQuYXJyYW5nZSBzbyBjYW4gc2VlIGFsbCBxdWFudCB2YXJpYWJsZXMgdG9nZXRoZXIgZ3JvdXAgYnkgbW9zdCBwcmVmZXJyZWQgdGltaW5ncwpncmlkLmFycmFuZ2UoCiAgCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gYXR0X21vc3RfcHJlZl90aW1lLCB5ID0gYXR0X2Rpc3RhbmNlKSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCgogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IGF0dF9tb3N0X3ByZWZfdGltZSwgeSA9IHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIG5jb2wgPSAyCikKYGBgCgotIFBlb3BsZSB3aG8gYXJlIGxpa2VseSB0byBhdHRlbmQgbWF0Y2hlcyBpbiAyMDE3IHByZWZlciBhIGdhbWUgb24gU3VuZGF5IEV2ZW5pbmdzCgojIyBBdHRlbmRhbmNlIFRpY2tldCBUeXBlCmBgYHtyfQojIENvZGUgaGlzdG9ncmFtcyB1c2luZyBncmlkLmFycmFuZ2Ugc28gY2FuIHNlZSBhbGwgcXVhbnQgdmFyaWFibGVzIHRvZ2V0aGVyIGdyb3VwIGJ5IHRpY2tldCB0eXBlCmdyaWQuYXJyYW5nZSgKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBzYWxlc190aWNrZXRfdHlwZSwgeSA9IGF0dF9kaXN0YW5jZSkpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IHNhbGVzX3RpY2tldF90eXBlLCB5ID0gbWVkaWFfc2Vhc29uX25ld3NwYXBlcikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IHNhbGVzX3RpY2tldF90eXBlLCB5ID0gbWVkaWFfc2Vhc29uX3R2KSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gc2FsZXNfdGlja2V0X3R5cGUsIHkgPSBzYWxlc19udW1vZm1hdGNoXzIwMTcpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGNvb3JkX2ZsaXAoKSwKICBuY29sID0gMgopCmBgYAoKLSBQZW9wbGUgd2hvIGFyZSB0cmF2ZWxsaW5nIG1heGltdW0gZGlzdGFuY2VzIGFyZSBtb3JlIGxpa2VseSB0byBidXkgc2luZ2xlIG1hdGNoIHRpY2tldHMKLSBQZW9wbGUgd2hvIGFyZSBtb3JlIGxpa2VseSB0byBhdHRlbmQgU2Vhc29uIDIwMTcsIHByZWZlciB0byBidXkgU2Vhc29uIFRpY2tldCAKCiMjTWVkaWEgYWR2ZXJ0aXNlbWVudHMKCmBgYHtyfQojIENvZGUgaGlzdG9ncmFtcyB1c2luZyBncmlkLmFycmFuZ2Ugc28gY2FuIHNlZSBhbGwgcXVhbnQgdmFyaWFibGVzIHRvZ2V0aGVyIGdyb3VwIGJ5IGFkdmVydGlzZW1lbnRzCgpncmlkLmFycmFuZ2UoCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gbWVkaWFfd2ViLCB5ID0gYXR0X2Rpc3RhbmNlKSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCiAgc2VhX3JlaWduX2RhdGEgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gbWVkaWFfd2ViLCB5ID0gbWVkaWFfc2Vhc29uX25ld3NwYXBlcikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IG1lZGlhX3dlYiwgeSA9IG1lZGlhX3NlYXNvbl90dikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IG1lZGlhX3dlYiwgeSA9IHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIG5jb2wgPSAyCikKYGBgCgotICBDbGVhcmx5LCB3ZWJzaXRlIGlzIHRoZSBtb3N0IHBvcHVsYXIgbWVkaWEsIGZhY2Vib29rIGlzIHNlY29uZAoKIyNNZXJjaGFuZGlzZSBCdXlpbmcgUHJlZmVyZW5jZXMKCmBgYHtyfQojIENvZGUgaGlzdG9ncmFtcyB1c2luZyBncmlkLmFycmFuZ2Ugc28gY2FuIHNlZSBhbGwgcXVhbnQgdmFyaWFibGVzIHRvZ2V0aGVyIGdyb3VwIGJ5IGJ1eWluZyBwcmVmZXJlbmNlcwoKZ3JpZC5hcnJhbmdlKAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IG1lcl9idXlfcHJlZiwgeSA9IHNhbGVzX2V4cF9zZWxmMjAxNikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgY29vcmRfZmxpcCgpLAogIHNlYV9yZWlnbl9kYXRhICU+JSAKICAgIGdncGxvdChhZXMoeCA9IG1lcl9idXlfcHJlZiwgeSA9IHNhbGVzX2V4cF9vdGgyMDE2KSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBjb29yZF9mbGlwKCksCiAgICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBtZXJfYnV5X3ByZWYsIHkgPSBzYWxlc19udW1vZm1hdGNoXzIwMTcpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGNvb3JkX2ZsaXAoKSwKICBuY29sID0gMgopCmBgYAoKLSBJbiB0aGUgeWVhciAyMDE2LCBtb3N0IHBlb3BsZSBzcGVuZCBvbiBzZWxmIGFuZCBvdGhlcnMgYnkgT25saW5lIG1lcmNoYW5kaXNlIHB1cmNoYXNlcyAKICAtIFNlY29uZCBwcmVmZXJlbmNlIHdhcyBleHBlbmRpdHVyZSBkdXJpbmcgdGhlIG1hdGNoCi0gUGVvcGxlIHdobyBhcmUgbGlrZWx5IHRvIGF0dGVuZCB0aGUgbWF0Y2ggaW4gMjAxNywgaGF2ZSBhIGJ1eWluZyBwcmVmZXJlbmNlIG9mIE9ubGluZSBhcyBtYXhpbXVtCgozLiBVbml2YXJpYXRlIG5vbi1ncmFwaGljYWwg4oCTIFF1YW50aXRhdGl2ZQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKYGBge3J9CiMgRGVzY3JpcHRpdmUgc3RhdGlzdGljcwpzdW1tYXJ5KHNlYV9yZWlnbl9kYXRhKQpgYGAKCjQuIFVuaXZhcmlhdGUgZ3JhcGhpY2FsICAtIFF1YW50aXRhdGl2ZQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKIyNIaXN0b2dyYW1zCgpgYGB7cn0KIyBDb2RlIGhpc3RvZ3JhbXMgdXNpbmcgZ3JpZC5hcnJhbmdlIHNvIGNhbiBzZWUgYWxsIHF1YW50IHZhcmlhYmxlcyB0b2dldGhlcgoKCmdyaWQuYXJyYW5nZSgKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKGF0dF9kaXN0YW5jZSkpICsKICAgICAgZ2VvbV9oaXN0b2dyYW0oKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICsKICAgICAgZ2VvbV9oaXN0b2dyYW0oKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHNhbGVzX2V4cF9zZWxmMjAxNikpICsKICAgICAgZ2VvbV9oaXN0b2dyYW0oKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHNhbGVzX2V4cF9vdGgyMDE2KSkgKwogICAgICBnZW9tX2hpc3RvZ3JhbSgpLAogIAogIG5jb2wgPSAyCikKCmBgYAotIE1heGltdW0gY291bnQgaXMgZm9yIGxlYXN0IGRpc3RhbmNlIHRyYXZlbGxlZCBwZW9wbGUgd2hvIGFyZSBhdHRlbmRpbmcgdGhlIG1hdGNoCi0gTWF4aW11bSBjb3VudCBpcyAwIGZvciBleHBlbmRpdHVyZSBmb3Igc2VsZiwgdmVyeSBmZXcgaGF2ZSBoaWdoZXIgZXhwZW5zZXMKCgojI0JveHBsb3RzCgpgYGB7cn0KCiMgU2V0IGdyaWQgcGF0dGVybiBmb3IgZ3JhcGggYXJyYW5nZW1lbnQKcGFyKG1mcm93ID0gYygyLCAyKSkKYm94cGxvdChzZWFfcmVpZ25fZGF0YSRhdHRfZGlzdGFuY2UsIG1haW4gPSAiQXR0ZW5kYW5jZV9kaXN0YW5jZV90cmF2ZWxsZWQiKQpib3hwbG90KHNlYV9yZWlnbl9kYXRhJHNhbGVzX251bW9mbWF0Y2hfMjAxNywgbWFpbiA9ICJTYWxlc19OdW1iZXJPZk1hdGNoZXMiKQpib3hwbG90KHNlYV9yZWlnbl9kYXRhJHNhbGVzX2V4cF9zZWxmMjAxNiwgbWFpbiA9ICJTYWxlc19FeHBlbmRpdHVyZV9TZWxmMjAxNiIpCmJveHBsb3Qoc2VhX3JlaWduX2RhdGEkc2FsZXNfZXhwX290aDIwMTYsIG1haW4gPSAiU2FsZXNfRXhwZW5kaXR1cmVfT3RoZXJzMjAxNiIpCmBgYAoKCjUuIE11bHRpdmFyaWF0ZSBub24tZ3JhcGhpY2FsIC0gQ2F0ZWdvcmljYWwKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojI0Nyb3NzdGFicwpDcm9zcy10YWJzIGFyZSB1c2VkIGZvciB0YWJ1bGF0aW9uIG9mIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwoKYGBge3J9CmFkZG1hcmdpbnMoeHRhYnMofiBhdHRfZmlyc3RfYXR0ZW5kICsgYXR0X2ludGVyZXN0LCBkYXRhID0gc2VhX3JlaWduX2RhdGEpKQpgYGAKCmBgYHtyfQphZGRtYXJnaW5zKHh0YWJzKH4gYXR0X2ZpcnN0X2F0dGVuZCArIGF0dF9wcm9tb19lZmZlY3QsIGRhdGEgPSBzZWFfcmVpZ25fZGF0YSkpCmBgYAoKYGBge3J9CmFkZG1hcmdpbnMoeHRhYnMofiBhdHRfZmlyc3RfYXR0ZW5kICsgYXR0X21vc3RfcHJlZl90aW1lLCAgZGF0YSA9IHNlYV9yZWlnbl9kYXRhKSkKYGBgCgpgYGB7cn0KYWRkbWFyZ2lucyh4dGFicyh+IHNhbGVzX251bW9mbWF0Y2hfMjAxNyArIG1lZGlhX3dlYiwgIGRhdGEgPSBzZWFfcmVpZ25fZGF0YSkpCmBgYAoKYGBge3J9CmFkZG1hcmdpbnMoeHRhYnMofiBzYWxlc19udW1vZm1hdGNoXzIwMTcgKyBtZXJfYnV5X3ByZWYsICBkYXRhID0gc2VhX3JlaWduX2RhdGEpKQpgYGAKCmBgYHtyfQphZGRtYXJnaW5zKHh0YWJzKH4gc2FsZXNfbnVtb2ZtYXRjaF8yMDE3ICsgbWVyX3B1cmNoYXNlX3Nwb25zb3JzLCAgZGF0YSA9IHNlYV9yZWlnbl9kYXRhKSkKYGBgCgpgYGB7cn0KYWRkbWFyZ2lucyh4dGFicyh+IHNhbGVzX251bW9mbWF0Y2hfMjAxNyArIGRlbV9nZW5kZXIsICBkYXRhID0gc2VhX3JlaWduX2RhdGEpKQpgYGAKCmBgYHtyfQphZGRtYXJnaW5zKHh0YWJzKH4gc2FsZXNfbnVtb2ZtYXRjaF8yMDE3ICsgZGVtX21hcml0YWxfc3RhdHVzLCAgZGF0YSA9IHNlYV9yZWlnbl9kYXRhKSkKYGBgCgpgYGB7cn0KYWRkbWFyZ2lucyh4dGFicyh+IHNhbGVzX251bW9mbWF0Y2hfMjAxNyArIGRlbV9lZHVjYXRpb24sICBkYXRhID0gc2VhX3JlaWduX2RhdGEpKQpgYGAKCiMjIyMjT2JzZXJ2YXRpb25zCgotIFdpdGggMjQ5IHBlb3BsZSBhdHRlbmRpbmcgbWF0Y2gsIFN1bmRheSBldmVuaW5ncyBpcyBtb3N0IGZhdm9yaXRlLCBhdHRlbmRhbmNlIGRlY3JlYXNlZCBmcm9tIDgyIHRvIDQ1IGluIDIwMTYgCi0gUGVvcGxlIHdobyBhcmUgbGlrZWx5IHRvIGF0dGVuZCAyMDE3IG1hdGNoLCBmb2xsb3dpbmcgU2VhdHRsZSBGQyBSZWlnbiBvbiB3ZWJzaXRlCi0gTWF4aW11bSBwZW9wbGUgd2hvIGFyZSBsaWtlbHkgdG8gYXR0ZW5kIGEgMjAxNyBtYXRjaCBwcmVmZXIgdG8gcHVyY2hhc2UgT25saW5lCi0gTW9zdCBwb3B1bGFyIHNwb25zb3IgYW1vbmcgcGVvcGxlIGxpa2VseSB0byBhdHRlbmQgYSAyMDE3IG1hdGNoIHByZWZlciBNaWNyb3NvZnQgYXMgYSBzcG9uc29yCi0gTW9zdCBwb3B1bGFyIG1lcmNoYW5kaXNlIGFtb25nIHBlb3BsZSBsaWtlbHkgdG8gYXR0ZW5kIGEgMjAxNyBtYXRjaCBpcyBzaG9ydCBzbGVldmUgc2hpcnQKLSBGZW1hbGUgZmFucyBhbmQgbWFycmllZCBwZW9wbGUgYXJlIG1vcmUgaW4gbnVtYmVycyB0aGFuIG1hbGUgZmFucyBhbmQgc2luZ2xlIHdobyBhcmUgZ29pbmcgdG8gYXR0ZW5kIGEgMjAxNyBtYXRjaAotIFNvbWVvbmUgd2l0aCBhIGJhY2hlbG9yIG9yIGdyYWR1YXRlIGRlZ3JlZSBhcmUgaW50ZXJlc3RlZCBpbiB3YXRjaGluZyAyMDE3IG1hdGNoCgojI1Byb3BvcnRpb24gQ3Jvc3MgVGFiCgpgYGB7cn0KIyBQcm9wb3J0aW9ucyBtaWdodCBiZSBtb3JlIGluZm9ybWF0aXZlCmFkZG1hcmdpbnMocm91bmQocHJvcC50YWJsZSh4dGFicyh+IGF0dF9maXJzdF9hdHRlbmQgKyBhdHRfaW50ZXJlc3QsICBkYXRhID0gc2VhX3JlaWduX2RhdGEpKSwgMykpCmBgYAoKNi4gTXVsdGktdmFyaWF0ZSBncmFwaGljYWwgLSBDYXRlZ29yaWNhbAo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKKipVc2UgdGlsZSBwbG90IHRvIHNob3cgbXVsdGl2YXJpYXRlIGNhdGVnb3JpY2FsKioKCgpgYGB7cn0KIyBOb3RlIGhhdmUgdG8gY2FsY3VsYXRlIGFuZCBwcm92aWRlIGEgdmFyaWFibGUgZm9yIGZpbGxpbmcgdGhlIGdyYXBoCgpzZWFfcmVpZ25fZGF0YSAlPiUKICBncm91cF9ieShhdHRfbW9zdF9wcmVmX3RpbWUsIGF0dF9hdHRlbmRfMjAxNikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIAogIGdncGxvdChhZXMoYXR0X21vc3RfcHJlZl90aW1lLCBhdHRfYXR0ZW5kXzIwMTYpKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBnZW9tX3RpbGUoYWVzKGZpbGwgPSAtY291bnQpKQoKc2VhX3JlaWduX2RhdGEgJT4lCiAgZ3JvdXBfYnkoc2FsZXNfdGt0X3R5cGVfMjAxNywgYXR0X2F0dGVuZF8yMDE3KSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyhzYWxlc190a3RfdHlwZV8yMDE3LCBhdHRfYXR0ZW5kXzIwMTcpKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBnZW9tX3RpbGUoYWVzKGZpbGwgPSAtY291bnQpKQoKc2VhX3JlaWduX2RhdGEgJT4lCiAgZ3JvdXBfYnkobWVkaWFfd2ViLCBhdHRfYXR0ZW5kXzIwMTcpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSAKICBnZ3Bsb3QoYWVzKG1lZGlhX3dlYiwgYXR0X2F0dGVuZF8yMDE3KSkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgZ2VvbV90aWxlKGFlcyhmaWxsID0gLWNvdW50KSkKCnNlYV9yZWlnbl9kYXRhICU+JQogIGdyb3VwX2J5KG1lcl9idXlfcHJlZiwgYXR0X2F0dGVuZF8yMDE2KSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyhtZXJfYnV5X3ByZWYsIGF0dF9hdHRlbmRfMjAxNikpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGdlb21fdGlsZShhZXMoZmlsbCA9IC1jb3VudCkpCmBgYAoKLSBTdW5kYXkgZXZlbmluZ3MgaXMgbW9zdCBwb3B1bGFyIHRpbWluZwotIFNpbmdsZSBtYXRjaGVzIGFuZCBzZWFzb25hbCB0aWNrZXRzIGFyZSBtb3N0IGxpa2VseSB0byBzZWxsCgo3LiBNdWx0aXZhcmlhdGUgbm9uLWdyYXBoaWNhbCAtIFF1YW50aXRhdGl2ZQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojI0NvcnJlbGF0aW9ucyBwbG90cyAgCgpgYGB7cn0KCiMgVXNlIGdncGFpcnMgZnJvbSB0aGUgR0dhbGx5IHBhY2thZ2UKY29yX3Bsb3QgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KGF0dF9kaXN0YW5jZSxzYWxlc19leHBfc2VsZjIwMTYsc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSAgIAoKY29yKGNvcl9wbG90KQpgYGAKCgotIFBlb3BsZSB3aG8gYXJlIGxpa2VseSB0byBhdHRlbmQgY2VydGFpbiBudW1iZXIgb2YgbWF0Y2hlcyBpbiAyMDE3IGFuZCBkb2xsYXIgYW1vdW50IHBlb3BsZSBoYXZlIHNwZW50IG92ZXIgdGhlICgyMDE2KSBzZWFzb24gb24gU2VhdHRsZSBSZWlnbiBGQyBtZXJjaGFuZGlzZSBhbmQgc3dhZyAobm90IGZvb2QpIGZvciBzZWxmIGFyZSBwb3NpdGl2ZWx5IGNvcnJlbGF0ZWQgKDM0LjIlKQoKCjguIE11bHRpdmFyaWF0ZSBncmFwaGljYWwgLSBRdWFudGl0YXRpdmUKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKIyMgQ29ycmVsYXRpb25zIHBhcml3aXNlIHBsb3QKCmBgYHtyfQojIFBhaXJ3aXNlIHBsb3QKCnBhaXJzX3Bsb3QgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KGF0dF9kaXN0YW5jZSxzYWxlc19leHBfc2VsZjIwMTYsc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KQoKcGFpcnNfcGxvdCAlPiUKICBnZ3BhaXJzKCkKCnBhaXJzLnBhbmVscyhwYWlyc19wbG90KQoKYGBgCiAgCiMjIyMjIE9ic2VydmF0aW9ucyBvZiB0aGUgZGF0YSAKCioqV2l0aCBtb3JlIHBlb3BsZSBsaWtlbHkgdG8gYXR0ZW5kIGEgMjAxNyBtYXRjaGVzLCB0aGVyZSBhcmUgY2hhbmNlcyB0aGF0IHBlb3BsZSBtaWdodCBzcGVuZCBtb3JlIG9uIG1lcmNoYW5kaXNlIGFzIGluIDIwMTYqKgoKCmBgYHtyfQojIFN0YW5kYXJkIHNjYXR0ZXIgcGxvdCB0byB2aXN1YWxpemUgd2hhdCBpcyB0aGUgcmV2ZW51ZSB3aGVuIHByb2R1Y2VycyByZWNlaXZlIG1heGltdW0gcHJvbW9zIGFuZCBhZHMKCmdyaWQuYXJyYW5nZSgKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdHRfYXR0ZW5kXzIwMTYsIHkgPSBzYWxlc19udW1vZm1hdGNoXzIwMTcsIGNvbG9yID0gZGVtX2dlbmRlcikpICsKICAgIGdlb21fcG9pbnQoKSArIAogICAgZ2VvbV9qaXR0ZXIoKSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSwKICBzZWFfcmVpZ25fZGF0YSAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBhdHRfYXR0ZW5kXzIwMTcsIHkgPSBzYWxlc19udW1vZm1hdGNoXzIwMTcsIGNvbG9yID0gZGVtX2dlbmRlcikpICsKICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBnZW9tX2ppdHRlcigpICsKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUmVkcyIpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpLAogICAgCiAgbmNvbCA9IDIKKQpgYGAKCgotIEZlbWFsZSBoYXZlIGF0dGVuZGVkIG1vcmUgbWF0Y2hlcyBpbiB0aGUgcGFzdCwgaW4gMjAxNyBmZW1hbGVzIGFyZSBsaWtlbHkgdG8gYXR0ZW5kIG1vcmUgYXMgd2VsbAoKOS4gTXVsdGl2YXJpYXRlIG5vbi1ncmFwaGljYWwgLSBDYXRlZ29yaWNhbCBhbmQgUXVhbnRpdGF0aXZlIAo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCmBgYHtyfQojIEZvcm0gdGFibGUgb2YgbWVkaWFucyAKIyBBdHRlbmRhbmNlIHdoZW4gMjAxNiA9IDEgCmF0dGVuZGFuY2VfMjAxNiA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBncm91cF9ieShtZXJfYnV5X3ByZWYsIGRlbV9nZW5kZXIpICU+JQogIGZpbHRlcihhdHRfYXR0ZW5kXzIwMTYgPT0gMSkgJT4lCiAgc3VtbWFyaXNlKFN1bV9kaXN0YW5jZSA9IG1lYW4oYXR0X2Rpc3RhbmNlKSkgJT4lCiAgc3ByZWFkKGRlbV9nZW5kZXIsIFN1bV9kaXN0YW5jZSkgJT4lCiAgYXMuZGF0YS5mcmFtZSgpCgphdHRlbmRhbmNlXzIwMTYKCmBgYAoKLSBPYnNlcnZhdGlvbiB3aGVuIGF0dGVuZGVkIG1hdGNoIGluIDIwMTYgPSAxCi0gRmVtYWxlIHdobyBoYXMgYXR0ZW5kZWQgYSAyMDE2IG1hdGNoIGFuZCBoYXMgYSBidXlpbmcgcHJlZmVyZW5jZSBhdCBzdG9yZSB0cmF2ZWxsZWQgYXBwcm94aW1hdGVseSAxOC42IG1pbGVzIHRvIHNlZSB0aGUgbWF0Y2gKCgoxMC4gTXVsdGl2YXJpYXRlIG5vbi1ncmFwaGljYWwgLSBDYXRlZ29yaWNhbCBhbmQgUXVhbnRpdGF0aXZlIAo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojI1BhcnQxIC0gQ2x1c3RlcmVkIGJhcnBsb3RzIGFjcm9zcyBhdHRlbmRhbmNlLCBtZWRpYSBhbmQgbWVyY2hhbmRpc2UKCiMjIzEuIEFjcm9zcyBNZXJjaGFuZGlzZQoKKipDbHVzdGVyZWQgYmFycGxvdCB0byBjb21wYXJlIGRpc3RhbmNlIHRyYXZlbGxlZCwgZXhwZW5kaXR1cmUgb24gc2VsZiwgbnVtYmVyIG9mIG1hdGNoZXMgYXR0ZW5kaW5nIGluIDIwMTcgYWNyb3NzIE1lcmNoYW5kaXNlKioKCgpgYGB7cn0KCiMgRmlyc3QgZ2V0IHRoZSBkYXRhIGFuZCBuYW1lIHRoZSBncmFwaCBzbyB3ZSBjYW4gYnVpbGQgaXQgYnkgbGF5ZXIKbWVyY2hhbmRpc2VfZGF0YTEgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KGF0dF9kaXN0YW5jZSxtZXJfYnV5X3ByZWYpICU+JSAKICBncm91cF9ieShtZXJfYnV5X3ByZWYpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIEdyb3VwX2J5IGlzIGJ5IGZhY3RvciBsZXZlbCwgc28gZ3JvdXAgYnkgYXR0ZW5kYW5jZQogIHN1bW1hcmlzZV9hbGwoZnVucyhtZWFuKSkgJT4lICAgICAgICAgICAgICMgVGFrZSB0aGUgbWVhbiBvZiBhbGwgcmVtYWluaW5nIGNvbHVtbnMgc28gd2UgY2FuIGdyYXBoIHRoZW0KICBnYXRoZXIoIlZhcmlhYmxlIiwgIk1lYW4iLCAtKG1lcl9idXlfcHJlZikpICAgICAjIGdhdGhlciBpcyB1c2VkIHRvIHJlc2hhcGUgdGhlIGRhdGEsIG1ha2UgYSBiYXIgZ3JhcGggYnkgIlZhcmlhYmxlIgoKbWVyY2hhbmRpc2VfZGF0YTIgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KHNhbGVzX2V4cF9zZWxmMjAxNixtZXJfYnV5X3ByZWYpICU+JSAKICBncm91cF9ieShtZXJfYnV5X3ByZWYpICU+JSAKICBzdW1tYXJpc2VfYWxsKGZ1bnMobWVhbikpICU+JSAKICBnYXRoZXIoIlZhcmlhYmxlIiwgIk1lYW4iLCAtKG1lcl9idXlfcHJlZikpCgptZXJjaGFuZGlzZV9kYXRhMyA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBzZWxlY3Qoc2FsZXNfZXhwX290aDIwMTYsbWVyX2J1eV9wcmVmKSAlPiUgCiAgZ3JvdXBfYnkobWVyX2J1eV9wcmVmKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5zKG1lYW4pKSAlPiUgCiAgZ2F0aGVyKCJWYXJpYWJsZSIsICJNZWFuIiwgLShtZXJfYnV5X3ByZWYpKQoKbWVyY2hhbmRpc2VfZGF0YTQgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KHNhbGVzX251bW9mbWF0Y2hfMjAxNyxtZXJfYnV5X3ByZWYpICU+JSAKICBncm91cF9ieShtZXJfYnV5X3ByZWYpICU+JSAKICBzdW1tYXJpc2VfYWxsKGZ1bnMobWVhbikpICU+JSAKICBnYXRoZXIoIlZhcmlhYmxlIiwgIk1lYW4iLCAtKG1lcl9idXlfcHJlZikpCgptZXJjaGFuZGlzZV9kYXRhNSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBzZWxlY3QoYXR0X2Rpc3RhbmNlLHNhbGVzX2V4cF9zZWxmMjAxNixzYWxlc19udW1vZm1hdGNoXzIwMTcsbWVyX2J1eV9wcmVmKSAlPiUgCiAgZ3JvdXBfYnkobWVyX2J1eV9wcmVmKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5zKG1lYW4pKSAlPiUgCiAgZ2F0aGVyKCJWYXJpYWJsZSIsICJNZWFuIiwgLShtZXJfYnV5X3ByZWYpKQoKbWVyY2hhbmRpc2VfZGF0YTEKbWVyY2hhbmRpc2VfZGF0YTIKbWVyY2hhbmRpc2VfZGF0YTMKbWVyY2hhbmRpc2VfZGF0YTQKCmBgYAoKYGBge3J9CiMgTm93IHNldCBmcmFtZSBmb3IgcGxvdCwgbm90aWNlIG5ldyB2YXJpYWJsZXMgIlZhcmlhYmxlIiBhbmQgIk1lYW4iCmdyaWQuYXJyYW5nZSgKbWVyY2hhbmRpc2VfcGxvdDEgPC0gbWVyY2hhbmRpc2VfZGF0YTEgJT4lICAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwgIyBTZXQgc3RhdCBhbmQgcG9zaXRpb24gdG8gZ2V0IHNpZGUtYnktc2lkZSBiYXIKCm1lcmNoYW5kaXNlX3Bsb3QyIDwtIG1lcmNoYW5kaXNlX2RhdGEyICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwKCm1lcmNoYW5kaXNlX3Bsb3QzIDwtIG1lcmNoYW5kaXNlX2RhdGEzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwKCm1lcmNoYW5kaXNlX3Bsb3Q0IDwtIG1lcmNoYW5kaXNlX2RhdGE0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSkKCm1lcmNoYW5kaXNlX3Bsb3Q1IDwtIG1lcmNoYW5kaXNlX2RhdGE1ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKQoKYGBgCgojIyMjIE9ic2VydmF0aW9ucyAKCi0gUGVvcGxlIHdobyBoYXZlIHNwZW50IG1vc3Qgb24gc2VsZiBpbiAyMDE2IHNlYXNvbiBhcmUgbW9zdCBsaWtlbHkgdG8gcHVyY2hhc2UgbWVyY2hhbmRpc2UgYXQgc3RvcmVzCi0gUGVvcGxlIHdobyBhcmUgcGxhbm5pbmcgdG8gYXR0ZW5kIGEgbWF0Y2ggaW4gMjAxNyBhcmUgbW9zdCBsaWtlbHkgdG8gcHVyY2hhc2UgbWVyY2hhbmRpc2UgYXQgc3RvcmVzCgoKIyMjIDIuIEFjcm9zcyBNZWRpYQoKKipDbHVzdGVyZWQgYmFycGxvdCB0byBjb21wYXJlIGRpc3RhbmNlIHRyYXZlbGxlZCwgZXhwZW5kaXR1cmUgb24gc2VsZiwgbnVtYmVyIG9mIG1hdGNoZXMgYXR0ZW5kaW5nIGluIDIwMTcgZm9yIE1lZGlhKioKCmBgYHtyfQoKbWVkaWFfZGF0YTEgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KGF0dF9kaXN0YW5jZSxtZWRpYV93ZWIpICU+JSAKICBncm91cF9ieShtZWRpYV93ZWIpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIEdyb3VwX2J5IGlzIGJ5IGZhY3RvciBsZXZlbCwgc28gZ3JvdXAgYnkgbWVkaWEKICBzdW1tYXJpc2VfYWxsKGZ1bnMobWVhbikpICU+JSAgICAgICAgICAgICAjIFRha2UgdGhlIG1lYW4gb2YgYWxsIHJlbWFpbmluZyBjb2x1bW5zIHNvIHdlIGNhbiBncmFwaCB0aGVtCiAgZ2F0aGVyKCJWYXJpYWJsZSIsICJNZWFuIiwgLShtZWRpYV93ZWIpKSAgICAgIyBnYXRoZXIgaXMgdXNlZCB0byByZXNoYXBlIHRoZSBkYXRhLCBtYWtlIGEgYmFyIGdyYXBoIGJ5ICJWYXJpYWJsZSIKCm1lZGlhX2RhdGEyIDwtIHNlYV9yZWlnbl9kYXRhICU+JQogIHNlbGVjdChzYWxlc19leHBfc2VsZjIwMTYsbWVkaWFfd2ViKSAlPiUgCiAgZ3JvdXBfYnkobWVkaWFfd2ViKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5zKG1lYW4pKSAlPiUgCiAgZ2F0aGVyKCJWYXJpYWJsZSIsICJNZWFuIiwgLShtZWRpYV93ZWIpKQoKbWVkaWFfZGF0YTMgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KHNhbGVzX2V4cF9vdGgyMDE2LG1lZGlhX3dlYikgJT4lIAogIGdyb3VwX2J5KG1lZGlhX3dlYikgJT4lIAogIHN1bW1hcmlzZV9hbGwoZnVucyhtZWFuKSkgJT4lIAogIGdhdGhlcigiVmFyaWFibGUiLCAiTWVhbiIsIC0obWVkaWFfd2ViKSkKCm1lZGlhX2RhdGE0IDwtIHNlYV9yZWlnbl9kYXRhICU+JQogIHNlbGVjdChzYWxlc19udW1vZm1hdGNoXzIwMTcsbWVkaWFfd2ViKSAlPiUgCiAgZ3JvdXBfYnkobWVkaWFfd2ViKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChmdW5zKG1lYW4pKSAlPiUgCiAgZ2F0aGVyKCJWYXJpYWJsZSIsICJNZWFuIiwgLShtZWRpYV93ZWIpKQoKbWVkaWFfZGF0YTUgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgc2VsZWN0KGF0dF9kaXN0YW5jZSxzYWxlc19leHBfc2VsZjIwMTYsc2FsZXNfbnVtb2ZtYXRjaF8yMDE3LG1lZGlhX3dlYikgJT4lIAogIGdyb3VwX2J5KG1lZGlhX3dlYikgJT4lIAogIHN1bW1hcmlzZV9hbGwoZnVucyhtZWFuKSkgJT4lIAogIGdhdGhlcigiVmFyaWFibGUiLCAiTWVhbiIsIC0obWVkaWFfd2ViKSkKCgptZWRpYV9kYXRhMQptZWRpYV9kYXRhMgptZWRpYV9kYXRhMwptZWRpYV9kYXRhNAoKCmBgYAoKYGBge3J9CiMgU2V0IGZyYW1lIGZvciBwbG90LCBub3RpY2UgbmV3IHZhcmlhYmxlcyAiVmFyaWFibGUiIGFuZCAiTWVhbiIKCmdyaWQuYXJyYW5nZSgKbWVkaWFfcGxvdDEgPC0gbWVkaWFfZGF0YTEgJT4lICAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZWRpYV93ZWIpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwgIyBTZXQgc3RhdCBhbmQgcG9zaXRpb24gdG8gZ2V0IHNpZGUtYnktc2lkZSBiYXIKCm1lZGlhX3Bsb3QyIDwtIG1lZGlhX2RhdGEyICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZWRpYV93ZWIpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwKCm1lZGlhX3Bsb3QzIDwtIG1lZGlhX2RhdGEzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZWRpYV93ZWIpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSwKCm1lZGlhX3Bsb3Q0IDwtIG1lZGlhX2RhdGE0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZWRpYV93ZWIpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSkKCm1lZGlhX3Bsb3Q1IDwtIG1lZGlhX2RhdGE1ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBWYXJpYWJsZSwgeSA9IE1lYW4sIGZpbGwgPSBtZWRpYV93ZWIpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKQoKYGBgCgojIyMjIE9ic2VydmF0aW9ucwoKLSBQZW9wbGUgd2hvIGZvbGxvdyBSZWlnbiBvbiBJbnN0YWdyYW0gYXJlIHRyYXZlbGxpbmcgbWF4aW11bSBkaXN0YW5jZSB0byBhdHRlbmQgdGhlIGdhbWUKXyBQZW9wbGUgd2hvIGRpZCBtYXhpbXVtIGV4cGVuZGl0dXJlIGluIHNlYXNvbiAyMDE2LCBmb2xsb3cgUmVpZ25zIG9uIFR3aXR0ZXIKLSBQZW9wbGUgd2hvIGFyZSBsaWtlbHkgdG8gYXR0ZW5kIHNlYXNvbiAyMDE3LCBmb2xsb3cgUmVpZ25zIG9uIEluc3RhZ3JhbQoKIyNQYXJ0MiAtIENsdXN0ZXJlZCBiYXJwbG90IHdpdGggcHJvZmVzc2lvbmFsIGdyYXBocwoKTGV0cyBhZGQgYSB0aXRsZSBhbmQgc29tZSBiYXIgdGV4dCAgCgpgYGB7cn0KICAgICAgIyBBZGQgbGFiZWxzIHRvIGVhY2ggYmFyCm1lcmNoYW5kaXNlX3Bsb3QgPC0gbWVyY2hhbmRpc2VfcGxvdDUgKyBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQoTWVhbiwgMSkpLCB2anVzdCA9IC0wLjUsIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSguOSksIHNpemUgPSA0KSArCiAgICAgICMgQWRkIGEgbWFpbiB0aXRsZQogICAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBvZiBkaXN0YW5jZSxleHBlbmRpdHVyZSBhbmQgbWF0Y2hlcyBpbiAyMDE3IGJ5IGJ1eWluZyBwcmVmZXJlbmNlIiwKICAgIHN1YnRpdGxlID0gIkhpZ2hlc3QgbWVhbiBleHBlbmRpdHVyZSBvbiBzZWxmIGluIDIwMTYgc2Vhc29uIGlzIGF0IHN0b3JlXG5IaWdoZXN0IG1lYW4gZGlzdGFuY2UgdHJhdmVsbGVkIHRvIHB1cmNoYXNlIG1lcmNoYW5kaXNlIGluIHN0b3JlIikgKwogICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgICB0aGVtZShheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksICMgVXNlIHRoZW1lIHRvIGNsZWFuIHVwIHRoZSBncmFwaCB0byBtYWtlIG1vcmUgcHJvZmVzc2lvbmFsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpCgojIENhbGwgdGhlIGdyYXBoCm1lcmNoYW5kaXNlX3Bsb3QKYGBgCgoKYGBge3J9CiAgICAgICMgQWRkIGxhYmVscyB0byBlYWNoIGJhcgptZWRpYV9wbG90IDwtIG1lZGlhX3Bsb3Q1ICsgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKE1lYW4sIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpLCBzaXplID0gMykgKwogICAgICAjIEFkZCBhIG1haW4gdGl0bGUKICAgIGdndGl0bGUoIkNvbXBhcmlzb24gb2YgZGlzdGFuY2UsZXhwZW5kaXR1cmUgYW5kIG1hdGNoZXMgaW4gMjAxNyBieSBidXlpbmcgcHJlZmVyZW5jZSIsCiAgICBzdWJ0aXRsZSA9ICJIaWdoZXN0IG1lYW4gZXhwZW5kaXR1cmUgb24gc2VsZiBpbiAyMDE2IHNlYXNvbiBpcyBhdCBzdG9yZVxuSGlnaGVzdCBtZWFuIGRpc3RhbmNlIHRyYXZlbGxlZCB0byBwdXJjaGFzZSBtZXJjaGFuZGlzZSBpbiBzdG9yZSIpICsKICAgIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiUHVCdUduIikgKwogICAgdGhlbWUoYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLCAjIFVzZSB0aGVtZSB0byBjbGVhbiB1cCB0aGUgZ3JhcGggdG8gbWFrZSBtb3JlIHByb2Zlc3Npb25hbAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKQoKIyBDYWxsIHRoZSBncmFwaAptZWRpYV9wbG90CmBgYAoKCiMjUGFydDMgLSBCYXIgcGxvdHMKCgojIyBhLiBGYWN0b3JzIHRoYXQgaGF2ZSBpbXBhY3Qgb24gYXR0ZW5kYW5jZT8KCmBgYHtyfQojIERvaW5nIGEgc3Vic2V0IG9mIHRoZSB0YWJsZSB0byBqdXN0IHNob3cgdmFyaWFibGVzIG9mIGludGVyZXN0CnRpbWluZ3Nfc3Vic2V0IDwtIGMoIldlZCBFdmVuaW5ncyIsICJTdW5kYXkgRXZlbmluZ3MiLCJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iLCJGcmlkYXkgRXZlbmluZ3MiLCAiU2F0dXJkYXkgRXZlbmluZ3MiLCAKICAgICAgICAgICAgICAgICAgICAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iLCAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iLCJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIpCgpwYXN0X3llYXJfYXR0ZW5kYW5jZSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBmaWx0ZXIoYXR0X21vc3RfcHJlZl90aW1lICVpbiUgdGltaW5nc19zdWJzZXQpCgphdHRlbmRhbmNlX3Bsb3QgPC0gcGFzdF95ZWFyX2F0dGVuZGFuY2UgJT4lCiAgZ3JvdXBfYnkoYXR0X21vc3RfcHJlZl90aW1lLCBhdHRfZmlyc3RfYXR0ZW5kKSAlPiUKICBzdW1tYXJpemUoYXZnX2Rpc3RhbmNlID0gbWVhbihhdHRfZGlzdGFuY2UpKSAKICBnZ3Bsb3QoZGF0YSA9IGF0dGVuZGFuY2VfcGxvdCwgYWVzKHggPSByZW9yZGVyKGF0dF9tb3N0X3ByZWZfdGltZSwgYXZnX2Rpc3RhbmNlKSwgeSA9IGF2Z19kaXN0YW5jZSAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gYXR0X2ZpcnN0X2F0dGVuZCkpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlB1QnVHbiIpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPSJkb2RnZSIpICsKICBjb29yZF9mbGlwKCkKYGBgCiAKIyMgYi4gRmFjdG9ycyB0aGF0IGhhdmUgaW1wYWN0IG9uIGF0dGVuZGFuY2UgbGlrZSB0aW1pbmdzIG9mIHRoZSBtYXRjaD8KCmBgYHtyfQojIERvaW5nIGEgc3Vic2V0IG9mIHRoZSB0YWJsZSB0byBqdXN0IHNob3cgdmFyaWFibGVzIG9mIGludGVyZXN0CnRpbWluZ3Nfc3Vic2V0IDwtIGMoIldlZCBFdmVuaW5ncyIsICJTdW5kYXkgRXZlbmluZ3MiLCJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iLCJGcmlkYXkgRXZlbmluZ3MiLCAiU2F0dXJkYXkgRXZlbmluZ3MiLCAKICAgICAgICAgICAgICAgICAgICAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iLCAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iLCJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIpCgpuZXh0X3llYXJfYXR0ZW5kYW5jZSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICAjZmlsdGVyKGF0dF9hdHRlbmRfMjAxNyAlaW4lIGF0dGVuZF8yMDE3X3N1YnNldCkgJT4lCiAgZmlsdGVyKGF0dF9tb3N0X3ByZWZfdGltZSAlaW4lIHRpbWluZ3Nfc3Vic2V0KQoKYXR0ZW5kYW5jZV9wbG90MSA8LSBuZXh0X3llYXJfYXR0ZW5kYW5jZSAlPiUKICBncm91cF9ieShhdHRfbW9zdF9wcmVmX3RpbWUsIGF0dF9hdHRlbmRfMjAxNykgJT4lCiAgc3VtbWFyaXplKGF2Z19kaXN0YW5jZSA9IG1lYW4oYXR0X2Rpc3RhbmNlKSkgCiAgZ2dwbG90KGRhdGEgPSBhdHRlbmRhbmNlX3Bsb3QxLCBhZXMoeCA9IHJlb3JkZXIoYXR0X21vc3RfcHJlZl90aW1lLCBhdmdfZGlzdGFuY2UpLCB5ID0gYXZnX2Rpc3RhbmNlICwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBhdHRfYXR0ZW5kXzIwMTcpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKIyMgYy4gRmFjdG9ycyB0aGF0IGhhdmUgaW1wYWN0IG9uIGF0dGVuZGFuY2UgYXVkaWVuY2VzIGxpa2UgdG8gd2F0Y2ggdGhlIGdhbWV3aXRoPwoKYGBge3J9CiMgRG9pbmcgYSBzdWJzZXQgb2YgdGhlIHRhYmxlIHRvIGp1c3Qgc2hvdyB2YXJpYWJsZXMgb2YgaW50ZXJlc3QKZ2FtZXdpdGhfc3Vic2V0IDwtIGMoIjMgTWF0Y2ggUGFjayIsIlNpbmdsZSBNYXRjaCIsIkkgZG9uJ3Qga25vdyIsIjUgTWF0Y2ggUGFjayIsIlNlYXNvbiBUaWNrZXQiKQoKdGlja2V0X3R5cGUgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgZmlsdGVyKHNhbGVzX3RpY2tldF90eXBlICVpbiUgZ2FtZXdpdGhfc3Vic2V0KQoKYXR0ZW5kYW5jZV9wbG90MiA8LSB0aWNrZXRfdHlwZSAlPiUKICBncm91cF9ieShzYWxlc190aWNrZXRfdHlwZSxhdHRfZ2FtZXdpdGgpICU+JQogIHN1bW1hcml6ZShhdmdfZGlzdGFuY2UgPSBtZWFuKGF0dF9kaXN0YW5jZSkpIAogIGdncGxvdChkYXRhID0gYXR0ZW5kYW5jZV9wbG90MiwgYWVzKHggPSByZW9yZGVyKHNhbGVzX3RpY2tldF90eXBlLCBhdmdfZGlzdGFuY2UpLCB5ID0gYXZnX2Rpc3RhbmNlICwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBhdHRfZ2FtZXdpdGgpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKIyNkLiBIb3cgbXVjaCBkaWQgcGVvcGxlIHNwZW50IG9uIG1lcmNoYW5kaXNlIG9uIHNlbGYgYW5kIG90aGVycyBpZiB0aGV5IGF0dGVuZGVkIGEgbWF0Y2ggaW4gMjAxNj8KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9IEZBTFNFfQojIERvaW5nIGEgc3Vic2V0IG9mIHRoZSB0YWJsZSB0byBqdXN0IHNob3cgdmFyaWFibGVzIG9mIGludGVyZXN0Cm1lcl9zdWJzZXQgPC0gYygiQXQgU3RvcmUiLCJEdXJpbmcgTWF0Y2giLCJPbmxpbmUiKQoKbWVyY19wcmVmIDwtIHNlYV9yZWlnbl9kYXRhICU+JQogIGZpbHRlcihtZXJfYnV5X3ByZWYgJWluJSBtZXJfc3Vic2V0KQojIFdlIHdhbnQgdG8gYW5hbHl6ZSBpZiBtb3JlIHVuaXRzIGFyZSBwdXJjaGFzZWQgaWYgcHJpY2UgcGVyIHBhY2thZ2VzIGFyZSBsb3dlciAKIyBXZSBjYW4gYW5hbHl6ZSB0aGlzIGJ5IHBsb3R0aW5nIHByaWNlIChwcmljZSBwZXIgcGFja2FnZSkgYnkgdW5pdHMgYm91Z2h0CgphdHRlbmRfbGFiZWxzIDwtIGMoIjAiID0gIk5vdCBhdHRlbmRlZCAyMDE2IiwgIjEiID0gIkF0dGVuZGVkIDIwMTYiKQpzYWxlc19wbG90IDwtIAptZXJjX3ByZWYgJT4lCiAgZ2dwbG90KChhZXMoeCA9IHNhbGVzX2V4cF9zZWxmMjAxNiwgeSA9IGF0dF9kaXN0YW5jZSwgY29sPSBtZXJfYnV5X3ByZWYpKSkrIAogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9RkFMU0UpICsgICAjIEFkZCBsaW5lYXIgcmVncmVzc2lvbiBsaW5lCiAgZmFjZXRfZ3JpZCgufiBhdHRfYXR0ZW5kXzIwMTYsIGxhYmVsbGVyID0gbGFiZWxsZXIoYXR0X2F0dGVuZF8yMDE2ID0gYXR0ZW5kX2xhYmVscykpICsKICBnZ3RpdGxlKCJNZXJjaGFuZGlzZSBidXlpbmcgcHJlZmVyZW5jZXMgZm9yIHBlb3BsZSB3aG8gYXR0ZW5kZWQgMjAxNiBzZWFzb24iLCAKICBzdWIgPSAiRmFucyBmcm9tICIpICsKICBsYWJzKHggPSAiUHJpY2VzIChVU0QpIHVuZGVyIHByb21vIHNldHRpbmciLCAKICAgICAgIHkgPSAiVW5pdHMgc29sZCBhdCBnaXZlbiBwcmljZSIsCiAgICAgICBjb2wgPSAiUHJvZHVjZXJzIikgKyAKICB0aGVtZV9idygpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlB1QnVHbiIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpKQoKCnNhbGVzX3Bsb3QKCgpgYGAKIyNlLiBNZXJjaGFuZGlzZSBwcmVmZXJlbmNlcyA/CgoKYGBge3J9CiMgRG9pbmcgYSBzdWJzZXQgb2YgdGhlIHRhYmxlIHRvIGp1c3Qgc2hvdyB2YXJpYWJsZXMgb2YgaW50ZXJlc3QKdGltaW5nc19zdWJzZXQgPC0gYygiV2VkIEV2ZW5pbmdzIiwgIlN1bmRheSBFdmVuaW5ncyIsIlN1bmRheSBBZnRlcm5vb25zIDRwbSIsIkZyaWRheSBFdmVuaW5ncyIsICJTYXR1cmRheSBFdmVuaW5ncyIsIAogICAgICAgICAgICAgICAgICAgICJTYXR1cmRheSBBZnRlcm5vb25zIDRwbSIsICJTYXR1cmRheSBBZnRlcm5vb25zIDRwbSIsIlNhdHVyZGF5IEFmdGVybm9vbnMgMXBtIikKCmF0dGVuZF8yMDE3X3N1YnNldCA8LSBjKCJBdHRlbmRfMjAxNyIsIk5ldXRyYWwiKQoKbmV4dF95ZWFyX2F0dGVuZGFuY2UgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgZmlsdGVyKGF0dF9hdHRlbmRfMjAxNyAlaW4lIGF0dGVuZF8yMDE3X3N1YnNldCkgJT4lCiAgZmlsdGVyKGF0dF9tb3N0X3ByZWZfdGltZSAlaW4lIHRpbWluZ3Nfc3Vic2V0KQoKbWVyY2hhbmRpc2VfcGxvdCA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBncm91cF9ieShtZXJfcmVpZ24sIG1lcl9idXlfcHJlZikgJT4lCiAgc3VtbWFyaXplKGF2Z19leHBlbmRpdHVyZSA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSkgCiAgZ2dwbG90KGRhdGEgPSBtZXJjaGFuZGlzZV9wbG90LCBhZXMoeCA9IHJlb3JkZXIobWVyX3JlaWduLCBhdmdfZXhwZW5kaXR1cmUpLCB5ID0gYXZnX2V4cGVuZGl0dXJlICwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBtZXJfYnV5X3ByZWYpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQdUJ1R24iKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZG9kZ2UiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKUmVzZWFyY2ggUXVlc3Rpb25zCj09PT09PT09PT09PT09PT09PQoKIyNRdWVzdGlvbiAxOiBVbmRlcnN0YW5kIHRoZSBtZXJjaGFuZGlzZSBidXlpbmcgcHJlZmVyZW5jZXMgYW5kIGF2ZXJhZ2UgZXhwZW5kaXR1cmUgb3ZlciB0aGUgMjAxNiBzZWFzb24gZm9yIHBlb3BsZSB3aG8gaGF2ZSBhdHRlbmRlZCAyMDE2IHNlYXNvbi4KCiMjMS4gRmlyc3QgZXhhbWluZSB0aGUgYnV5aW5nIHByZWZlcmVuY2VzIG9mIHBlb3BsZSB3aG8gaGF2ZSBhdHRlbmRlZCB0aGUgbWF0Y2ggaW4gMjAxNiBzZWFzb24KCmBgYHtyfQptZXJfc3Vic2V0IDwtIGMoIkR1cmluZyBNYXRjaCIsIk9ubGluZSIsIkF0IFN0b3JlIikKbWVyX3JlaWduX3N1YnNldCA8LSBjKCJTaG9ydF9TbGVldmVfU2hpcnQiLCJMb25nX1NsZWV2ZV9TaGlydCIsIkFjY2Vzc29yaWVzIiwiSmFja2V0cyIpCgptZXJjaGFuZGlzZSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBmaWx0ZXIobWVyX2J1eV9wcmVmICVpbiUgbWVyX3N1YnNldCkgJT4lCiAgZmlsdGVyKG1lcl9yZWlnbiAlaW4lIG1lcl9yZWlnbl9zdWJzZXQpCgptZXJjaGFuZGlzZSAlPiUgCiAgZmlsdGVyKGF0dF9hdHRlbmRfMjAxNiA9PSAxKSAlPiUKICBncm91cF9ieShtZXJfYnV5X3ByZWYpICU+JSAKICBzdW1tYXJpc2UoQ291bnQgPSBuKCksCiAgQXZlcmFnZV9FeHBlbmRpdHVyZV9TZWxmID0gbWVhbihzYWxlc19leHBfc2VsZjIwMTYpLAogIEF2ZXJhZ2VfRXhwZW5kaXR1cmVfT3RoZXJzID0gbWVhbihzYWxlc19leHBfb3RoMjAxNikpICU+JQogIGFycmFuZ2UoZGVzYyhBdmVyYWdlX0V4cGVuZGl0dXJlX1NlbGYpKSAlPiUKICBrYWJsZSgpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIsICJyZXNwb25zaXZlIikpICU+JQogIHJvd19zcGVjKDEsIGJhY2tncm91bmQgPSAiI2U1ZjVlMCIpCmBgYAoKKipOdWxsIEh5cG90aGVzaXM6IEF2ZXJhZ2UgZXhwZWRpbnR1cmUgaXMgc2FtZSBhY3Jvc3MgYWxsIG1lcmNoYW5kaXNlIGZvciBwZW9wbGUgd2hvIGF0dGVuZGVkIHNlYXNvbiAyMDE2KioKCmBgYHtyfQpzZWFfaHlwMSA8LSBtZXJjaGFuZGlzZSAlPiUKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE2ID09IDEpIAoKIyBJcyBleHBlbmRpdHVyZSB0aGUgc2FtZSBhY3Jvc3MgbWVyY2hhbmRpc2VzPwp0LnRlc3Qoc2VhX2h5cDEkc2FsZXNfZXhwX3NlbGYyMDE2W3NlYV9oeXAxJG1lcl9idXlfcHJlZiA9PSAiRHVyaW5nIE1hdGNoIl0sIAogICAgICAgc2VhX2h5cDEkc2FsZXNfZXhwX3NlbGYyMDE2W3NlYV9oeXAxJG1lcl9idXlfcHJlZiA9PSAiQXQgU3RvcmUiXSkKYGBgCgpgYGB7cn0Kc2VhX2h5cDEgPC0gbWVyY2hhbmRpc2UgJT4lCiAgZmlsdGVyKGF0dF9hdHRlbmRfMjAxNiA9PSAxKSAKCiMgSXMgZXhwZW5kaXR1cmUgdGhlIHNhbWUgYWNyb3NzIG1lcmNoYW5kaXNlcz8KdC50ZXN0KHNlYV9oeXAxJHNhbGVzX2V4cF9zZWxmMjAxNltzZWFfaHlwMSRtZXJfYnV5X3ByZWYgPT0gIkR1cmluZyBNYXRjaCJdLCAKICAgICAgIHNlYV9oeXAxJHNhbGVzX2V4cF9zZWxmMjAxNltzZWFfaHlwMSRtZXJfYnV5X3ByZWYgPT0gIk9ubGluZSJdKQpgYGAKCmBgYHtyfQojR3JhcGhpbmcgdGhlIE1lcmNoYW5kaXNlIHByZWZlcmVuY2VzIGFuZCBtZWFuIGV4cGVuZGl0dXJlIG9uIHNlbGYuCiMgOTAlIENJLCBnZXQgei12YWx1ZSBmb3IgdXBwZXIgdGFpbCwgdXNlIC45NSBzaW5jZSBpcyBvbmUgc2lkZWQKeiA8LSBxbm9ybSguOTUpCgojIEluY29ycG9yYXRlIENJIGludG8gYmFyIGdyYXBoIG9mIG1lYW5zCnNlYV9oeXAxICU+JQogIGdyb3VwX2J5KG1lcl9idXlfcHJlZikgJT4lCiAgc3VtbWFyaXNlKG0gPSBtZWFuKHNhbGVzX2V4cF9zZWxmMjAxNiksIHNkID0gc2Qoc2FsZXNfZXhwX3NlbGYyMDE2KSwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIobWVyX2J1eV9wcmVmLG0pLCB5ID0gbSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBmaWxsID0gIiM5ZWNhZTEiKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG0gLSBjaSwgeW1heCA9IG0gKyBjaSksIAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgeGxhYigiIikgKwogIHlsYWIoIiIpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlB1QnVHbiIpICsKICB0aGVtZShheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCkpICsKICBnZ3RpdGxlKCJNZXJjaGFuZGlzZSBwcmVmZXJlbmNlcyBhbmQgbWVhbiBleHBlbmRpdHVyZSBvbiBzZWxmIiwKICAgICAgICAgIHN1YnRpdGxlID0gIk1heGltdW0gZXhwZW5kaXR1cmUgZHVyaW5nIG1hdGNoIikKYGBgCgotIFRoZSBleHBlbmRpdHVyZSBncmFwaCBhYm92ZSBzaG93cyB0aGF0IHRoZSBNZXJjaGFuZGlzZXMgYXJlIG1vcmUgbGlrZWx5IHRvIHNlbGwgT25saW5lIG9yIGR1cmluZyB0aGUgTWF0Y2gKCgojIzIuIEV4YW1pbmUgbWVyY2hhbmRpc2VzIHRoYXQgYXJlIHBvcHVsYXIgYW5kIHNlbGwgYXQgc3RvcmUsIG9ubGluZSBhbmQgZHVyaW5nIG1hdGNoIHdpdGggYW5kIHdpdGhvdXQgcHJvbW9zCgpgYGB7cn0KCm1lcl9yZWlnbl9zdWJzZXQgPC0gYygiU2hvcnRfU2xlZXZlX1NoaXJ0IiwiTG9uZ19TbGVldmVfU2hpcnQiLCJBY2Nlc3NvcmllcyIsIkphY2tldHMiKQoKbWVyX3QyIDwtIHNlYV9yZWlnbl9kYXRhICU+JQogIGZpbHRlcihtZXJfcmVpZ24gJWluJSBtZXJfcmVpZ25fc3Vic2V0KQoKc2VhX2RtIDwtIG1lcl90MiAlPiUKICBmaWx0ZXIobWVyX2J1eV9wcmVmID09ICJEdXJpbmcgTWF0Y2giKQoKI0NyZWF0ZSBhIHRhYmxlIG9mIEdlbmVyYWwgTWlsbHMgY2VyZWFscyBhbmQgdGhlaXIgbWVhbiByZXZlbnVlIHdoZW4gYW4gaW4tc3RvcmUgcHJvbW90aW9uIGlzIGhhcHBlbmluZy4KbWVyY2hhbmRpc2VfdDIgPC0gc2VhX2RtICU+JSAKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE2ID09IDEpICU+JQogIGdyb3VwX2J5KG1lcl9yZWlnbikgJT4lIAogIHN1bW1hcmlzZShDb3VudCA9IG4oKSwKICBBdmVyYWdlX0V4cGVuZGl0dXJlX1NlbGYgPSBtZWFuKHNhbGVzX2V4cF9zZWxmMjAxNiksCiAgQXZlcmFnZV9FeHBlbmRpdHVyZV9PdGhlcnMgPSBtZWFuKHNhbGVzX2V4cF9vdGgyMDE2KSkgJT4lCiAgYXJyYW5nZShkZXNjKEF2ZXJhZ2VfRXhwZW5kaXR1cmVfU2VsZikpICU+JQogIGthYmxlKCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkgJT4lCiAgcm93X3NwZWMoMSwgYmFja2dyb3VuZCA9ICIjZmVlMGQyIikKCm1lcmNoYW5kaXNlX3QyCmBgYAoKKipOdWxsIEh5cG90aGVzaXM6IEF2ZXJhZ2UgZXhwZW5kaXR1cmUgb24gc2VsZiBpcyBzaW1pbGFyIGZvciBwcm9tb3MgYW5kIHdpdGhvdXQgcHJvbW9zIGFjcm9zcyBhbGwgbWVyY2hhbmRpc2UqKgoKYGBge3J9CgojIElzIGV4cGVuZGl0dXJlIHRoZSBzYW1lIHdoZXRoZXIgcnVubmluZyBhIHByb21vIG9yIG5vdD8KdC50ZXN0KHNlYV9kbSRzYWxlc19leHBfc2VsZjIwMTZbc2VhX2RtJGF0dF9wcm9tb19lZmZlY3QgPT0gIk5vIGluZmx1ZW5jZSJdLCAKICAgICAgIHNlYV9kbSRzYWxlc19leHBfc2VsZjIwMTZbc2VhX2RtJGF0dF9wcm9tb19lZmZlY3QgIT0gIk5vIGluZmx1ZW5jZSJdKQoKYGBgCgpgYGB7cn0KCiMgSXMgZXhwZW5kaXR1cmUgdGhlIHNhbWUgd2hldGhlciBydW5uaW5nIGEgcHJvbW8gb3Igbm90Pwp0LnRlc3Qoc2VhX2RtJHNhbGVzX2V4cF9vdGgyMDE2W3NlYV9kbSRhdHRfcHJvbW9fZWZmZWN0ID09ICJObyBpbmZsdWVuY2UiXSwgCiAgICAgICBzZWFfZG0kc2FsZXNfZXhwX290aDIwMTZbc2VhX2RtJGF0dF9wcm9tb19lZmZlY3QgIT0gIk5vIGluZmx1ZW5jZSJdKQoKYGBgCgpgYGB7cn0KI0dyYXBoaW5nIG1lYW4gcHJvbW90aW9uYWwgZXhwZW5kaXR1cmUgYWNyb3NzIE1lcmNoYW5kaXNlLgojIDkwJSBDSSwgZ2V0IHotdmFsdWUgZm9yIHVwcGVyIHRhaWwsIHVzZSAuOTUgc2luY2UgaXMgb25lIHNpZGVkCnogPC0gcW5vcm0oLjk1KQoKIyBJbmNvcnBvcmF0ZSBDSSBpbnRvIGJhciBncmFwaCBvZiBtZWFucwptZXJfdDIgJT4lCiAgbXV0YXRlKHByb21vID0gaWZfZWxzZShhdHRfcHJvbW9fZWZmZWN0ID09ICJQb3NpdGl2ZSBpbmZsdWVuY2UiLCAiUG9zaXRpdmUiLCAiTm9uZSIpKSAlPiUKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE2ID09IDEpICU+JQogIyBtdXRhdGUoZ2VuZGVyID0gaWZfZWxzZShkZW1fZ2VuZGVyID09ICJGZW1hbGUiLCAiRmVtYWxlIiwgIk1hbGUiKSkgJT4lCiAgZ3JvdXBfYnkobWVyX3JlaWduLCBwcm9tbykgJT4lCiAgc3VtbWFyaXNlKG0gPSBtZWFuKHNhbGVzX2V4cF9zZWxmMjAxNiksIHNkID0gc2Qoc2FsZXNfZXhwX3NlbGYyMDE2KS8yMCwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIobWVyX3JlaWduLCBtKSwgeSA9IG0sIGZpbGwgPSBwcm9tbykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG0gLSBjaSwgeW1heCA9IG0gKyBjaSksIAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCIiKSArCiAgbGFicyhmaWxsID0gIlByb21vIikgKwogIHNjYWxlX2ZpbGxfYnJld2VyKCkgKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTEpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpICsKICBnZ3RpdGxlKCJNZWFuIGV4cGVuZGl0dXJlIG9uIHNlbGYgZHVyaW5nIG1hdGNoIGZvciBTZWFzb24gMjAxNiAgIiwKICAgICAgICAgIHN1YnRpdGxlID0gIlByb21vcyBhcmUgZWZmZWN0aXZlIGZvciBzaG9ydCBzbGVldmUgc2hpcnRzXG5hbmQgQWNjZXNzb3JpZXMiKQpgYGAKCmBgYHtyfQpiYXNlX3Bsb3QyIDwtIAptZXJfdDIgJT4lCiAgCiAgbXV0YXRlKHByb21vID0gaWZfZWxzZShhdHRfcHJvbW9fZWZmZWN0ID09ICJQb3NpdGl2ZSBpbmZsdWVuY2UiLCAiUG9zaXRpdmUiLCAiTm9uZSIpKSAlPiUKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE2ID09IDEpICU+JQogIGdyb3VwX2J5KG1lcl9yZWlnbiwgcHJvbW8pICU+JQogIHN1bW1hcmlzZShtID0gbWVhbihzYWxlc19leHBfc2VsZjIwMTYpLCBzZCA9IHNkKHNhbGVzX2V4cF9zZWxmMjAxNikvMjAsIAogICAgICAgICAgICBuID0gbigpLCBjaSA9IHogKiBzZC9zcXJ0KG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKG1lcl9yZWlnbiwgbSksIHkgPSBtLCBmaWxsID0gcHJvbW8pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNjApLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBkb2xsYXJfZm9ybWF0KHByZWZpeCA9ICIkIikpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHhsYWIoIiIpICsKICBsYWJzKGZpbGwgPSAiUHJvbW8iKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lLnggPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyZXkiKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpICsKICBzY2FsZV9maWxsX2JyZXdlcigpICsKICBnZ3RpdGxlKCJNZWFuIGV4cGVuZGl0dXJlIGR1cmluZyBtYXRjaCBmb3IgU2Vhc29uIDIwMTYgICIsCiAgICAgICAgICBzdWJ0aXRsZSA9ICJQcm9tb3MgYXJlIHN0YXRpc3RpY2FsbHkgZWZmZWN0aXZlIGZvciBzaG9ydCBzbGVldmUgc2hpcnRzXG5hbmQgQWNjZXNzb3JpZXMiKQpzYXZlLmltYWdlKCJiYXNlX3Bsb3QyLlJEYXRhIikKYmFzZV9wbG90MgoKYGBgCiAgIApgYGB7cn0KI1RhcmdldCBicmFuZAoKYmFzZXBsb3QzIDwtIAptZXJfdDIgJT4lCiAgI211dGF0ZShnZW5kZXIgPSBpZl9lbHNlKGRlbV9nZW5kZXIgPT0gIkZlbWFsZSIsICJGZW1hbGUiLCAiTWFsZSIpKSAlPiUKICBtdXRhdGUoc3BvbnNvciA9IGlmX2Vsc2UobWVyX3B1cmNoYXNlX3Nwb25zb3JzID09ICJCRUNVIiwgIkJFQ1UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShtZXJfcHVyY2hhc2Vfc3BvbnNvcnMgPT0gIk1pY3Jvc29mdCIsICJNU0ZUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKG1lcl9wdXJjaGFzZV9zcG9uc29ycyA9PSAiUGVwc2kiLCAiUGVwc2kiLCAiT3RoZXJzIikpKSklPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIGZpbHRlcihhdHRfYXR0ZW5kXzIwMTYgPT0gMSkgJT4lCiAgZ3JvdXBfYnkobWVyX3JlaWduLCBzcG9uc29yKSAlPiUKICBzdW1tYXJpc2UobSA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSwgc2QgPSBzZChzYWxlc19leHBfc2VsZjIwMTYpLzIwLCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihtZXJfcmVpZ24sIG0pLCB5ID0gbSwgZmlsbCA9IHNwb25zb3IpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCB3aWR0aD0wLjcpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDYwKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gZG9sbGFyX2Zvcm1hdChwcmVmaXggPSAiJCIpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCIiKSArCiAgbGFicyhmaWxsID0gIlNwb25zb3JzIikgKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTEpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIoKSArCiAgZ2d0aXRsZSgiUG9wdWxhciBzcG9uc29ycyBkdXJpbmcgU2Vhc29uIDIwMTYgICIsCiAgICAgICAgICBzdWJ0aXRsZSA9ICJQZXBzaSBpcyBoaWdoZXN0IHNlbGxpbmcgYnJhbmQgZm9yIFNob3J0IFNsZWV2ZVxuU2hpcnRzIGFuZCBKYWNrZXRzIikKc2F2ZS5pbWFnZSgiYmFzZXBsb3QzLlJEYXRhIikKYmFzZXBsb3QzCgpgYGAKCi0gQXMgZXZpZGVudCBmcm9tIHRoZSBhYm92ZSBncmFwaHMsIFNob3J0IFNsZWV2ZSBTaGlydHMgYW5kIEFjY2Vzc29yaWVzIHNlbGwgbW9zdCB3aGVuIHByb21vdGlvbnMgaGF2ZSBwb3NpdGl2ZSBpbmZsdWVuY2UgCgotIExvbmcgU2xlZXZlIFNoaXJ0cyBhbmQgSmFja2V0cyBhcmUgc2VsbGluZyBldmVuIGlmIHRoZXJlIGlzIG5vIGluZmx1ZW5jZSBvZiBwcm9tb3Rpb25zIHdoaWNoIG1lYW5zIGl0IGlzIGltcG9ydGFudCB0byBmb2N1cyBvbiBwcm9tb3Rpb25hbCBzdHJhdGVneSBmb3IgcHJvZHVjdHMgbGlrZSBTaG9ydCBTbGVldmUgU2hpcnRzIGFuZCBBY2Nlc3NvcmllcyAgCgpgYGB7cn0KbWVyX3N1YnNldCA8LSBjKCJEdXJpbmcgTWF0Y2giLCJPbmxpbmUiLCJBdCBTdG9yZSIpCm1lcl9yZWlnbl9zdWJzZXQgPC0gYygiU2hvcnRfU2xlZXZlX1NoaXJ0IiwiTG9uZ19TbGVldmVfU2hpcnQiLCJBY2Nlc3NvcmllcyIsIkphY2tldHMiKQoKbWVyY2hhbmRpc2VfdDEgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgZmlsdGVyKG1lcl9idXlfcHJlZiAlaW4lIG1lcl9zdWJzZXQpICU+JQogIGZpbHRlcihtZXJfcmVpZ24gJWluJSBtZXJfcmVpZ25fc3Vic2V0KQoKZ1N0b3JlIDwtIHNlYV9oeXAxICU+JQogICAgZmlsdGVyKG1lcl9idXlfcHJlZiA9PSAiQXQgU3RvcmUiKSAlPiUKICAgIGZpbHRlcihtZXJfcmVpZ24gIT0gIkFjY2Vzc29yaWVzIikgJT4lCiAgICBncm91cF9ieShtZXJfYnV5X3ByZWYsIG1lcl9yZWlnbikgJT4lCiAgICBzdW1tYXJpc2UobSA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSwgc2QgPSBzZChzYWxlc19leHBfc2VsZjIwMTYpLCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKG1lcl9yZWlnbiwgbSksIHkgPSBtKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgCiAgICAgICAgICAgICBmaWxsID0gIiNkZWViZjciKSArIAogICAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3NSkpICsgCiAgICB0aGVtZV9jbGFzc2ljKCkgKwogICAgdGhlbWUoYXhpcy5saW5lLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLmxpbmUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgZ2d0aXRsZSgiU3RvcmUiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IC0wLjA4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZqdXN0ID0gLTAuMzAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMSksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMC4yLDAuMiwwLjIsMC4yKSwgImNtIikpCgpnT25saW5lIDwtIHNlYV9oeXAxICU+JQogICAgZmlsdGVyKG1lcl9idXlfcHJlZiA9PSAiT25saW5lIikgJT4lCiAgICBncm91cF9ieShtZXJfYnV5X3ByZWYsIG1lcl9yZWlnbikgJT4lCiAgICBzdW1tYXJpc2UobSA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSwgc2QgPSBzZChzYWxlc19leHBfc2VsZjIwMTYpLCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKG1lcl9yZWlnbiwgbSksIHkgPSBtKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgCiAgICAgICAgICAgICBmaWxsID0gIiM5ZWNhZTEiKSArIAogICAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3NSkpICsKICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICB0aGVtZShheGlzLmxpbmUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiT25saW5lIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAtMC4wOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTEpLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuMiwwLjIsMC4yLDAuMiksICJjbSIpKQoKZ01hdGNoIDwtIHNlYV9oeXAxICU+JQogICAgZmlsdGVyKG1lcl9idXlfcHJlZiA9PSAiRHVyaW5nIE1hdGNoIikgJT4lCiAgICBncm91cF9ieShtZXJfYnV5X3ByZWYsIG1lcl9yZWlnbikgJT4lCiAgICBzdW1tYXJpc2UobSA9IG1lYW4oc2FsZXNfZXhwX3NlbGYyMDE2KSwgc2QgPSBzZChzYWxlc19leHBfc2VsZjIwMTYpLCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKG1lcl9yZWlnbiwgbSksIHkgPSBtKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgZmlsbCA9ICIjMzE4MmJkIikgKwogICAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3NSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGRvbGxhcl9mb3JtYXQocHJlZml4ID0gIiQiKSkgKwogICAgdGhlbWVfY2xhc3NpYygpICsKICAgIHRoZW1lKGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmV5IiksCiAgICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBnZ3RpdGxlKCJNYXRjaCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLTAuMDgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAtMC4zMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDExKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjIsMC4yLDAuMiwwLjIpLCAiY20iKSkKCmJhc2VfcGxvdDEgPC0gY293cGxvdDo6cGxvdF9ncmlkKGdTdG9yZSwgZ09ubGluZSwgZ01hdGNoLCAKICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLCBucm93ID0gMywgCiAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4zLCAwLjUsIDAuNTgpLAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gIkF2ZXJhZ2UgZXhwZW5kaXR1cmUgU2Vhc29uIDIwMTYiLAogICAgICAgICAgICAgICAgICAgbGFiZWxfc2l6ZSA9IDEyLAogICAgICAgICAgICAgICAgICAgaGp1c3QgPSAtMC45LAogICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxLjcpCnNhdmUuaW1hZ2UoImJhc2VfcGxvdDEuUkRhdGEiKQoKYmFzZV9wbG90MQpgYGAKCiMjUXVlc3Rpb24gMjogV2hpY2ggdHlwZSBvZiB0aWNrZXQgc2VsbHMgdGhlIG1vc3QgYW5kIGF0IHdoYXQgdGltaW5ncyBvZiB0aGUgZGF5IGZhbnMgbGlrZSB0byBhdHRlbmQgdGhlIG1hdGNoPwoKIyMxLiBGaXJzdCBleGFtaW5lIHRoZSB0aWNrZXQgcHJlZmVyZW5jZXMgb2YgcGVvcGxlIHdobyBhcmUgcGxhbm5pbmcgdG8gYXR0ZW5kIG1hdGNoZXMgaW4gc2Vhc29uIDIwMTcKCgpgYGB7cn0KIyBUaGUgcGFsZXR0ZSB3aXRoIHB1cnBsZXM6CmNiUGFsZXR0ZSA8LSBjKCIjZGRkYWVkIiwiI2M1YjRlMyIsICIjOTU3OGQzIiwgIiM3ZDU1YzciKQoKI1RhYmxlIGZvciB0aWNrZXQgdHlwZSBmb3IgZWZmZWN0aXZlbmVzcyBhY3Jvc3MgdGhlIHdob2xlIG1hcmtldC4KdGlja2V0X3N1YnNldCA8LSBjKCIzIE1hdGNoIFBhY2siLCI1IE1hdGNoIFBhY2siLCJTZWFzb24gVGlja2V0IiwiU2luZ2xlIE1hdGNoIikKCnRpY2tldF90MSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBmaWx0ZXIoc2FsZXNfdGt0X3R5cGVfMjAxNyAlaW4lIHRpY2tldF9zdWJzZXQpIAoKdGlja2V0X3QxICU+JSAKICBncm91cF9ieShzYWxlc190a3RfdHlwZV8yMDE3KSAlPiUgCiAgc3VtbWFyaXNlKENvdW50ID0gbigpLAogIFRvdGFsX21hdGNoZXMyMDE3ID0gc3VtKHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICU+JQogIGFycmFuZ2UoZGVzYyhUb3RhbF9tYXRjaGVzMjAxNykpICU+JQogIGthYmxlKCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkgJT4lCiAgcm93X3NwZWMoMSwgYmFja2dyb3VuZCA9ICIjZTVmNWUwIikKYGBgCgoqKk51bGwgSHlwb3RoZXNpczogUGVvcGxlIHdobyBhcmUgcGxhbm5pbmcgdG8gYXR0ZW5kIHNlYXNvbiAyMDE3LCB3b3VsZCBsaWtlIHRvIGJ1eSBhbGwgdHlwZXMgb2YgdGlja2V0cyAqKgoKYGBge3J9CnNlYV9oeXAyIDwtIHRpY2tldF90MSAlPiUKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE3ID09IDEpIAoKIyBJcyB0aWNrZXQgdHlwZSBzYW1lIGZvciBldmVyeW9uZSB3aG8gaXMgYXR0ZW5kaW5nIG1hdGNoIGluIDIwMTc/CnQudGVzdChzZWFfaHlwMiRzYWxlc19udW1vZm1hdGNoXzIwMTdbc2VhX2h5cDIkc2FsZXNfdGt0X3R5cGVfMjAxNyA9PSAiNSBNYXRjaCBQYWNrIl0sIAogICAgICAgc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJHNhbGVzX3RrdF90eXBlXzIwMTcgPT0gIlNlYXNvbiBUaWNrZXQiXSkKYGBgCgpgYGB7cn0Kc2VhX2h5cDIgPC0gdGlja2V0X3QxICU+JQogIGZpbHRlcihhdHRfYXR0ZW5kXzIwMTcgPT0gMSkgCgojIElzIHRpY2tldCB0eXBlIHNhbWUgZm9yIGV2ZXJ5b25lIHdobyBpcyBhdHRlbmRpbmcgbWF0Y2ggaW4gMjAxNz8KdC50ZXN0KHNlYV9oeXAyJHNhbGVzX251bW9mbWF0Y2hfMjAxN1tzZWFfaHlwMiRzYWxlc190a3RfdHlwZV8yMDE3ID09ICI1IE1hdGNoIFBhY2siXSwgCiAgICAgICBzZWFfaHlwMiRzYWxlc19udW1vZm1hdGNoXzIwMTdbc2VhX2h5cDIkc2FsZXNfdGt0X3R5cGVfMjAxNyA9PSAiU2luZ2xlIE1hdGNoIl0pCmBgYAoKYGBge3J9CnNlYV9oeXAyIDwtIHRpY2tldF90MSAlPiUKICBmaWx0ZXIoYXR0X2F0dGVuZF8yMDE3ID09IDEpIAoKIyBJcyB0aWNrZXQgdHlwZSBzYW1lIGZvciBldmVyeW9uZSB3aG8gaXMgYXR0ZW5kaW5nIG1hdGNoIGluIDIwMTc/CnQudGVzdChzZWFfaHlwMiRzYWxlc19udW1vZm1hdGNoXzIwMTdbc2VhX2h5cDIkc2FsZXNfdGt0X3R5cGVfMjAxNyA9PSAiNSBNYXRjaCBQYWNrIl0sIAogICAgICAgc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJHNhbGVzX3RrdF90eXBlXzIwMTcgPT0gIjMgTWF0Y2ggUGFjayJdKQpgYGAKCmBgYHtyfQojR3JhcGhpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGluLXN0b3JlIHByb21vdGlvbnMgYW5kIHJldmVudWUgYWNyb3NzIGNvbXBhbmllcy4KIyA5MCUgQ0ksIGdldCB6LXZhbHVlIGZvciB1cHBlciB0YWlsLCB1c2UgLjk1IHNpbmNlIGlzIG9uZSBzaWRlZAp6IDwtIHFub3JtKC45NSkKCiMgSW5jb3Jwb3JhdGUgQ0kgaW50byBiYXIgZ3JhcGggb2YgbWVhbnMKc2VhX2h5cDIgJT4lCiAgZ3JvdXBfYnkoc2FsZXNfdGt0X3R5cGVfMjAxNykgJT4lCiAgc3VtbWFyaXNlKG0gPSBtZWFuKHNhbGVzX251bW9mbWF0Y2hfMjAxNyksIHNkID0gc2Qoc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoc2FsZXNfdGt0X3R5cGVfMjAxNyxtKSwgeSA9IG0pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgZmlsbCA9ICIjOWVjYWUxIikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtIC0gY2ksIHltYXggPSBtICsgY2kpLCAKICAgICAgICAgICAgICAgIHdpZHRoID0gMC41LCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsKCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCIiKSArCiAgeWxhYigiIikgKwogIHRoZW1lKGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICMgVG8gdXNlIGZvciBmaWxscywgYWRkCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkgKwogIGdndGl0bGUoIkF2ZXJhZ2UgbnVtYmVyIG9mIHRpY2tldCBwZW9wbGUgYXJlIHBsYW5uaW5nIGJ1eSBmb3Igc2Vhc29uIDIwMTciLAogICAgICAgICAgc3VidGl0bGUgPSAiU2Vhc29uIHRpY2tldCBpcyBsaWtlbHkgdG8gc2VsbCB0aGUgbW9zdCIpCmBgYAoKLSBUaGUgZmlndXJlIGFib3ZlIGluZGljYXRlcyB0aGF0IFNlYXNvbiB0aWNrZXQgaXMgcHJlZGljdGVkIHRvIHNlbGwgaGlnaGVzdCBmb3IgdGhlIHVwY29taW5nIFNlYXNvbiAyMDE3Ci0gNSBNYXRjaCBQYWNrIGlzIGxlYXN0IGxpa2VseSB0byBzZWxsICAKCiMjMi4gRXhhbWluZSB3aGljaCB0aW1pbmdzIGFyZSBwb3B1bGFyIHdoZW4gcGVvcGxlIHdvdWxkIGxpa2UgdG8gYXR0ZW5kIHRoZSBtYXRjaGVzIGluIHNlYXNvbiAyMDE3IGFuZCBidXkgYSBzZWFzb24gdGlja2V0PwoKYGBge3J9CnRpbWluZ3Nfc3Vic2V0IDwtIGMoIlN1bmRheSBFdmVuaW5ncyIsIkZyaWRheSBFdmVuaW5ncyIsIAogICAgICAgICAgICAgICAgICAgICJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iLCAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iLCJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIpCgp0aWNrZXRfdDIgPC0gc2VhX3JlaWduX2RhdGEgJT4lCiAgZmlsdGVyKGF0dF9tb3N0X3ByZWZfdGltZSAlaW4lIHRpbWluZ3Nfc3Vic2V0KQoKc2VhX3N0IDwtIHRpY2tldF90MiAlPiUKICBmaWx0ZXIoc2FsZXNfdGt0X3R5cGVfMjAxNyA9PSAiU2Vhc29uIFRpY2tldCIpICU+JQogIG11dGF0ZShwcm9tbyA9IGlmX2Vsc2UoYXR0X3Byb21vX2VmZmVjdCA9PSAiUG9zaXRpdmUgaW5mbHVlbmNlIiwgIjEiLCAiMCIpKQoKI0NyZWF0ZSBhIHRhYmxlIG9mIG1vc3QgcHJlZmVycmVkIHRpbWluZyB3aGVuIHBlb3BsZSBhcmUgbGlrZWx5IHRvIGF0dGVuZCBhIG1hdGNoIGluIDIwMTcgc2Vhc29uCnRpY2tldF90MiA8LSBzZWFfc3QgJT4lIAogIGZpbHRlcihhdHRfYXR0ZW5kXzIwMTcgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoYXR0X21vc3RfcHJlZl90aW1lKSAlPiUgCiAgc3VtbWFyaXNlKENvdW50ID0gbigpLAogIFRvdGFsX21hdGNoZXMyMDE3ID0gc3VtKHNhbGVzX251bW9mbWF0Y2hfMjAxNykpICU+JQogIGFycmFuZ2UoZGVzYyhUb3RhbF9tYXRjaGVzMjAxNykpICU+JQogIGthYmxlKCkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiwgInJlc3BvbnNpdmUiKSkgJT4lCiAgcm93X3NwZWMoNSwgYmFja2dyb3VuZCA9ICIjZmVlMGQyIikKCnRpY2tldF90MgpgYGAKCi0gU3VuZGF5IEV2ZW5pbmdzIGlzIHRoZSBtb3N0IHBvcHVsYXIgdGltaW5nIGFtb25nIGZhbnMgdG8gYXR0ZW5kIHRoZSBTZWF0dGxlIFJlaWduIEZDIG1hdGNoCgoqKk51bGwgSHlwb3RoZXNpczogQXZlcmFnZSBudW1iZXIgdGlja2V0cyBzb2xkIHdpbGwgYmUgc2FtZSBhdCBhbGwgdGltaW5ncyB3aXRoIG9yIHdpdGhvdXQgcHJvbW9zIGZvciBTZWFzb24gMjAxNyAqKgoKYGBge3J9CnNlYV9oeXAyIDwtIHNlYV9zdCAlPiUKICBmaWx0ZXIocHJvbW8gPT0gMSkKCiMgSXMgbnVtYmVyIG9mIHRpY2tldHMgc29sZCBzYW1lIGF0IGFsbCB0aW1pbmdzIHdoZXRoZXIgcnVubmluZyBhIHByb21vIG9yIG5vdD8KdC50ZXN0KHNlYV9oeXAyJHNhbGVzX251bW9mbWF0Y2hfMjAxN1tzZWFfaHlwMiRhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlN1bmRheSBFdmVuaW5ncyJdLCAKICAgICAgIHNlYV9oeXAyJHNhbGVzX251bW9mbWF0Y2hfMjAxN1tzZWFfaHlwMiRhdHRfbW9zdF9wcmVmX3RpbWUgIT0gIkZyaWRheSBFdmVuaW5ncyJdKQoKYGBgCgpgYGB7cn0Kc2VhX2h5cDIgPC0gc2VhX3N0ICU+JQogIGZpbHRlcihwcm9tbyA9PSAxKQoKIyBJcyBudW1iZXIgb2YgdGlja2V0cyBzb2xkIHNhbWUgYXQgYWxsIHRpbWluZ3Mgd2hldGhlciBydW5uaW5nIGEgcHJvbW8gb3Igbm90Pwp0LnRlc3Qoc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU3VuZGF5IEV2ZW5pbmdzIl0sIAogICAgICAgc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJGF0dF9tb3N0X3ByZWZfdGltZSAhPSAiU2F0dXJkYXkgQWZ0ZXJub29ucyAxcG0iXSkKCmBgYAoKYGBge3J9CnNlYV9oeXAyIDwtIHNlYV9zdCAlPiUKICBmaWx0ZXIocHJvbW8gPT0gMSkKCiMgSXMgbnVtYmVyIG9mIHRpY2tldHMgc29sZCBzYW1lIGF0IGFsbCB0aW1pbmdzIHdoZXRoZXIgcnVubmluZyBhIHByb21vIG9yIG5vdD8KdC50ZXN0KHNlYV9oeXAyJHNhbGVzX251bW9mbWF0Y2hfMjAxN1tzZWFfaHlwMiRhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlN1bmRheSBFdmVuaW5ncyJdLCAKICAgICAgIHNlYV9oeXAyJHNhbGVzX251bW9mbWF0Y2hfMjAxN1tzZWFfaHlwMiRhdHRfbW9zdF9wcmVmX3RpbWUgIT0gIlN1bmRheSBBZnRlcm5vb25zIDRwbSJdKQoKYGBgCgpgYGB7cn0Kc2VhX2h5cDIgPC0gc2VhX3N0ICU+JQogIGZpbHRlcihwcm9tbyA9PSAxKQoKIyBJcyBudW1iZXIgb2YgdGlja2V0cyBzb2xkIHNhbWUgYXQgYWxsIHRpbWluZ3Mgd2hldGhlciBydW5uaW5nIGEgcHJvbW8gb3Igbm90Pwp0LnRlc3Qoc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU3VuZGF5IEV2ZW5pbmdzIl0sIAogICAgICAgc2VhX2h5cDIkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3W3NlYV9oeXAyJGF0dF9tb3N0X3ByZWZfdGltZSAhPSAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iXSkKCmBgYAoKYGBge3J9CiNHcmFwaGluZyBtZWFuIHByb21vdGlvbmFsIHJldmVudWUgYWNyb3NzIEdlbmVyYWwgTWlsbCBicmFuZGVkIGNlcmVhbHMuCiMgOTAlIENJLCBnZXQgei12YWx1ZSBmb3IgdXBwZXIgdGFpbCwgdXNlIC45NSBzaW5jZSBpcyBvbmUgc2lkZWQKeiA8LSBxbm9ybSguOTUpCgoKIyBJbmNvcnBvcmF0ZSBDSSBpbnRvIGJhciBncmFwaCBvZiBtZWFucwpzZWFfc3QgJT4lCiAgbXV0YXRlKHByb21vID0gaWZfZWxzZShhdHRfcHJvbW9fZWZmZWN0ID09ICJQb3NpdGl2ZSBpbmZsdWVuY2UiLCAiUG9zaXRpdmUiLCAiTm9uZSIpKSAlPiUKICBtdXRhdGUocHJlZl90aW1lID0gY2FzZV93aGVuKGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiRnJpZGF5IEV2ZW5pbmdzIiB+ICJGcmkgRXZlbmluZ3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTYXR1cmRheSBBZnRlcm5vb25zIDRwbSIgfiAiU2F0IEFmdDRwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlN1bmRheSBBZnRlcm5vb25zIDRwbSIgfiAiU3VuIEFmdDRwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlNhdHVyZGF5IEFmdGVybm9vbnMgMXBtIiB+ICJTYXQgQWZ0MXBtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU3VuZGF5IEV2ZW5pbmdzIiB+ICJTdW4gRXZlbmluZ3MiKSkgJT4lCiAgZ3JvdXBfYnkocHJlZl90aW1lLCBwcm9tbykgJT4lCiAgc3VtbWFyaXNlKG0gPSBtZWFuKHNhbGVzX251bW9mbWF0Y2hfMjAxNyksIHNkID0gc2Qoc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KS81LCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihwcmVmX3RpbWUsIG0pLCB5ID0gbSwgZmlsbCA9IHJlb3JkZXIocHJvbW8sbSkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtIC0gY2ksIHltYXggPSBtICsgY2kpLCAKICAgICAgICAgICAgICAgIHdpZHRoID0gMC41LCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSkpICsKICAKIyAgY29vcmRfZmxpcCgpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHhsYWIoIiIpICsKICBsYWJzKGZpbGwgPSAiUHJvbW8gRWZmZWN0IikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIGhqdXN0ID0gMSkpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArCiAgIyBUbyB1c2UgZm9yIGZpbGxzLCBhZGQKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKSArCiAgZ2d0aXRsZSgiTWVhbiBudW1iZXIgb2YgU2Vhc29uIFRpY2tldHMgbGlrZWx5IHRvIHNlbGwgaW4gU2Vhc29uIDIwMTciLAogICAgICAgICAgc3VidGl0bGUgPSAiUHJvbW9zIGFyZSBub3QgZWZmZWN0aXZlIG9uIHdlZWtlbmQgbWF0Y2hlcyIpCgoKCmBgYAoKYGBge3J9CiMgVGhlIHBhbGV0dGUgd2l0aCBwdXJwbGVzOgpjYlBhbGV0dGUgPC0gYygiI2RkZGFlZCIsIiNjNWI0ZTMiLCAiIzk1NzhkMyIsICIjN2Q1NWM3IikKCmJhc2VfcGxvdDUgPC0gCnNlYV9zdCAlPiUKICBtdXRhdGUocHJvbW8gPSBpZl9lbHNlKGF0dF9wcm9tb19lZmZlY3QgPT0gIlBvc2l0aXZlIGluZmx1ZW5jZSIsICJQb3NpdGl2ZSIsICJOb25lIikpICU+JQogIG11dGF0ZShwcmVmX3RpbWUgPSBjYXNlX3doZW4oYXR0X21vc3RfcHJlZl90aW1lID09ICJGcmlkYXkgRXZlbmluZ3MiIH4gIkZyaSBFdmVuaW5ncyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlNhdHVyZGF5IEFmdGVybm9vbnMgNHBtIiB+ICJTYXQgQWZ0NHBtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU3VuZGF5IEFmdGVybm9vbnMgNHBtIiB+ICJTdW4gQWZ0NHBtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU2F0dXJkYXkgQWZ0ZXJub29ucyAxcG0iIH4gIlNhdCBBZnQxcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTdW5kYXkgRXZlbmluZ3MiIH4gIlN1biBFdmVuaW5ncyIpKSAlPiUKICBncm91cF9ieShwcmVmX3RpbWUsIHByb21vKSAlPiUKICBzdW1tYXJpc2UobSA9IG1lYW4oc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSwgc2QgPSBzZChzYWxlc19udW1vZm1hdGNoXzIwMTcpLzUsIAogICAgICAgICAgICBuID0gbigpLCBjaSA9IHogKiBzZC9zcXJ0KG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKHByZWZfdGltZSwgbSksIHkgPSBtLCBmaWxsID0gcHJvbW8pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtLCAxKSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDIuNSkgKwojICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgeGxhYigiIikgKwogIHlsYWIoIk1lYW4iKSArCiAgbGFicyhmaWxsID0gIlByb21vIEVmZmVjdCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkgKwogIGdndGl0bGUoIlByZWRpY3RlZCBNZWFuIG51bWJlciBvZiBTZWFzb24gVGlja2V0cyBsaWtlbHkgdG8gc2VsbCBpbiBTZWFzb24gMjAxNyIsCiAgICAgICAgICBzdWJ0aXRsZSA9ICJQcm9tb3MgYXJlIHN0YXRpc3RpY2FsbHkgZWZmZWN0aXZlIG9uIFNhdCBhZnRlcm5vb24gb25seSIpCnNhdmUuaW1hZ2UoImJhc2VfcGxvdDUuUkRhdGEiKQoKYmFzZV9wbG90NQpgYGAKCmBgYHtyfQoKYXVkaWVuY2Vfc3Vic2V0IDwtIGMoIkNvbGxlZ2UgR3JhZHVhdGUiLCAiR3JhZHVhdGUgRGVncmVlIiwiU29tZSBDb2xsZWdlIiwgCiAgICAgICAgICAgICAgICAgICAgIkhpZ2ggU2Nob29sIEdyYWR1YXRlIikKdGltaW5nc19zdWJzZXQgPC0gYygiU3VuZGF5IEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAiU3VuZGF5IEFmdGVybm9vbnMgNHBtIiwgIlNhdHVyZGF5IEFmdGVybm9vbnMgNHBtIiwgIkZyaWRheSBFdmVuaW5ncyIsICJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIpCmF1ZGllbmNlX25ldyA8LSBzZWFfc3QgJT4lCiAgZmlsdGVyKGRlbV9lZHVjYXRpb24gJWluJSBhdWRpZW5jZV9zdWJzZXQpICU+JQogIGZpbHRlcihhdHRfbW9zdF9wcmVmX3RpbWUgJWluJSB0aW1pbmdzX3N1YnNldCkKCgpiYXNlX3Bsb3Q2IDwtCmF1ZGllbmNlX25ldyAlPiUKICBtdXRhdGUoYXVkaWVuY2UgPSBpZl9lbHNlKGRlbV9lZHVjYXRpb24gPT0gIlNvbWUgQ29sbGVnZSIsICJTb21lIENvbGxlZ2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShkZW1fZWR1Y2F0aW9uID09ICJHcmFkdWF0ZSBEZWdyZWUiLCAiR3JhZHVhdGUgRGVncmVlIiwgIkNvbGxlZ2UgR3JhZHVhdGUiKSkpICU+JQogIGdyb3VwX2J5KGF0dF9tb3N0X3ByZWZfdGltZSwgYXVkaWVuY2UpICU+JQogIHN1bW1hcmlzZShtZWFuID0gbWVhbihzYWxlc19udW1vZm1hdGNoXzIwMTcpLCBzZCA9IHNkKHNhbGVzX251bW9mbWF0Y2hfMjAxNyksIAogICAgICAgICAgICBuID0gbigpLCBjaSA9IHogKiBzZC9zcXJ0KG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGF0dF9tb3N0X3ByZWZfdGltZSwgbWVhbiksIHkgPSBtZWFuLCBmaWxsID0gYXVkaWVuY2UpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UyKHByZXNlcnZlID0gInNpbmdsZSIsIHBhZGRpbmcgPSAwKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSByb3VuZChtZWFuLCAxKSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKC45KSwgc2l6ZSA9IDIuNSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgeGxhYigiIikgKwogIHlsYWIoIk1lYW4iKSArCiAgbGFicyhmaWxsID0gIk1haW4gQXVkaWVuY2UiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzNSwgaGp1c3QgPSAxKSkgKwogIHRoZW1lKGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLCBzaXplID0gMTEpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkgKwogIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jYlBhbGV0dGUpICsKICBnZ3RpdGxlKCJQcmVkaWN0ZWQgbWVhbiBvZiB0YXJnZXQgYXVkaWVuY2UsIGxpa2VseSB0byBhdHRlbmQgU2Vhc29uIDIwMTciLAogICAgICAgICAgc3VidGl0bGUgPSAiU3VycHJpc2luZ2x5LCBvbmx5IENvbGxlZ2Ugc3R1ZGVudHMgYXJlIG1vcmUgbGlrZWx5XG50byBhdHRlbmQgbWF0Y2hlcyBvbiBTYXR1cmRheSBBZnRlcm5vb25zMXBtIikKc2F2ZS5pbWFnZSgiYmFzZV9wbG90Ni5SRGF0YSIpCgpiYXNlX3Bsb3Q2CmBgYAoKLSBJbiBjb21wYXJpc29uIHRvIG90aGVyIHByZWZlcnJlZCB0aW1pbmdzLCBTYXR1cmRheSBBZnRlcm5vb24gMXBtIGFuZCBTdW5kYXkgRXZlbmluZ3MgdGlja2V0cyBhcmUgbGlrZWx5IHRvIHNlbGwgbW9yZSB3aGVuIHByb21vdGlvbnMgYXJlIGVmZmVjdGl2ZSAKCmBgYHtyfQojIFRoZSBwYWxldHRlIHdpdGggcHVycGxlczoKY2JQYWxldHRlIDwtIGMoIiNkZGRhZWQiLCIjYzViNGUzIiwgIiM5NTc4ZDMiLCAiIzdkNTVjNyIpCgojVGFibGUgZm9yIHRpY2tldCB0eXBlIGZvciBlZmZlY3RpdmVuZXNzIGFjcm9zcyB0aGUgd2hvbGUgbWFya2V0Lgp0aWNrZXRfc3Vic2V0IDwtIGMoIjUgTWF0Y2ggUGFjayIsIlNlYXNvbiBUaWNrZXQiLCJTaW5nbGUgTWF0Y2giKQp0aW1pbmdzX3N1YnNldCA8LSBjKCJXZWQgRXZlbmluZ3MiLCAiU3VuZGF5IEV2ZW5pbmdzIiwiRnJpZGF5IEV2ZW5pbmdzIiwgCiAgICAgICAgICAgICAgICAgICAgIlN1bmRheSBBZnRlcm5vb25zIDRwbSIsICJTYXR1cmRheSBBZnRlcm5vb25zIDRwbSIsIlNhdHVyZGF5IEFmdGVybm9vbnMgMXBtIikKc2VhX3NtMSA8LSBzZWFfcmVpZ25fZGF0YSAlPiUKICBmaWx0ZXIoYXR0X21vc3RfcHJlZl90aW1lICVpbiUgdGltaW5nc19zdWJzZXQpICU+JQogIGZpbHRlcihzYWxlc190a3RfdHlwZV8yMDE3ICVpbiUgdGlja2V0X3N1YnNldCkKCmc1TWF0Y2hQYWNrIDwtIHNlYV9zbTEgJT4lCiAgICBmaWx0ZXIoc2FsZXNfdGlja2V0X3R5cGUgPT0gIjUgTWF0Y2ggUGFjayIpICU+JQogICAgZ3JvdXBfYnkoc2FsZXNfdGt0X3R5cGVfMjAxNywgYXR0X21vc3RfcHJlZl90aW1lKSAlPiUKICAgIHN1bW1hcmlzZShtID0gc3VtKHNhbGVzX251bW9mbWF0Y2hfMjAxNyksIHNkID0gc2Qoc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihhdHRfbW9zdF9wcmVmX3RpbWUsIG0pLCB5ID0gbSkpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIAogICAgICAgICAgICAgZmlsbCA9ICIjZGRkYWVkIikgKyAKICAgIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNzUpKSArIAogICAgdGhlbWVfY2xhc3NpYygpICsKICAgIHRoZW1lKGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy5saW5lLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGdndGl0bGUoIjUgTWF0Y2ggUGFjayIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLTAuMjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAtMC4zMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDExKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjIsMC4yLDAuMiwwLjIpLCAiY20iKSkKCmdTaW5nbGUgPC0gc2VhX3NtMSAlPiUKICAgIGZpbHRlcihzYWxlc190a3RfdHlwZV8yMDE3ID09ICJTaW5nbGUgTWF0Y2giKSAlPiUKICAgIGZpbHRlcihhdHRfbW9zdF9wcmVmX3RpbWUgIT0gIlN1bmRheSBFdmVuaW5ncyIpICU+JQogICAgZmlsdGVyKGF0dF9tb3N0X3ByZWZfdGltZSAhPSAiU3VuZGF5IEFmdGVybm9vbnMgNHBtIikgJT4lCiAgICBncm91cF9ieShzYWxlc190a3RfdHlwZV8yMDE3LCBhdHRfbW9zdF9wcmVmX3RpbWUpICU+JQogICAgc3VtbWFyaXNlKG0gPSBzdW0oc2FsZXNfbnVtb2ZtYXRjaF8yMDE3KSwgc2QgPSBzZChzYWxlc19udW1vZm1hdGNoXzIwMTcpLCAKICAgICAgICAgICAgbiA9IG4oKSwgY2kgPSB6ICogc2Qvc3FydChuKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGF0dF9tb3N0X3ByZWZfdGltZSwgbSksIHkgPSBtKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgCiAgICAgICAgICAgICBmaWxsID0gIiNjNWI0ZTMiKSArIAogICAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA3NSkpICsKICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICB0aGVtZShheGlzLmxpbmUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMubGluZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZ2d0aXRsZSgiU2luZ2xlIE1hdGNoIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAtMC4yMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IC0wLjMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTEpLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuMiwwLjIsMC4yLDAuMiksICJjbSIpKQoKZ1NlYXNvbiA8LSBzZWFfc20xICU+JQogICAgZmlsdGVyKHNhbGVzX3RrdF90eXBlXzIwMTcgPT0gIlNlYXNvbiBUaWNrZXQiKSAlPiUKICAgIGdyb3VwX2J5KHNhbGVzX3RrdF90eXBlXzIwMTcsIGF0dF9tb3N0X3ByZWZfdGltZSkgJT4lCiAgICBzdW1tYXJpc2UobSA9IHN1bShzYWxlc19udW1vZm1hdGNoXzIwMTcpLCBzZCA9IHNkKHNhbGVzX251bW9mbWF0Y2hfMjAxNyksIAogICAgICAgICAgICBuID0gbigpLCBjaSA9IHogKiBzZC9zcXJ0KG4pKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoYXR0X21vc3RfcHJlZl90aW1lLCBtKSwgeSA9IG0pKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCBmaWxsID0gIiM5NTc4ZDMiKSArCiAgICBjb29yZF9mbGlwKCkgKwoKICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICB0aGVtZShheGlzLmxpbmUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLmxpbmUueCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleSIpLAogICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgZ2d0aXRsZSgiU2Vhc29uIFRpY2tldCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLTAuMjIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmp1c3QgPSAwLjMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTEpLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuMiwwLjIsMC4yLDAuMiksICJjbSIpKQoKYmFzZV9wbG90NCA8LSBjb3dwbG90OjpwbG90X2dyaWQoZzVNYXRjaFBhY2ssIGdTaW5nbGUsIGdTZWFzb24sIAogICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsIG5yb3cgPSAzLCAKICAgICAgICAgICAgICAgICAgIHJlbF9oZWlnaHRzID0gYygwLjM1LCAwLjM1LCAwLjUpLAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gIlByZWRpY3RlZCBUaWNrZXQgU2FsZXMgU2Vhc29uIDIwMTciLAogICAgICAgICAgICAgICAgICAgbGFiZWxfc2l6ZSA9IDEyLAogICAgICAgICAgICAgICAgICAgaGp1c3QgPSAtMC45LAogICAgICAgICAgICAgICAgICAgdmp1c3QgPSAxLjcpCnNhdmUuaW1hZ2UoImJhc2VfcGxvdDQuUkRhdGEiKQoKYmFzZV9wbG90NApgYGAKClN1bW1hcnkgb2YgRURBCj09PT09PT09PT09PT09PQojIyNQb3NzaWJsZSBSZWNvbW1lbmRhdGlvbnMKClBvc3NpYmxlIHJlY29tbWVuZGF0aW9ucyBmb3IgU2VhdHRsZSBSZWlnbiBGQyB0byBpbmNyZWFzZSB0aWNrZXQgc2FsZXMgYW5kIGF0dGVuZGFuY2U6CgotIFB1cmNoYXNpbmcgaGFiaXRzIG9mIHZpc2l0b3JzLCBtb3N0IGxpa2VseSB0byBwdXJjaGFzZSBmcm9tIHN0b3JlcwoKLSBTZWF0dGxlIFJlaWduIEZDIGNhbiBmb2N1cyBvbiBzYWxlcyBvZiBTaG9ydCBTbGVldmUgU2hpcnRzIGR1cmluZyB0aGUgbWF0Y2ggYmVjYXVzZSBpdCBpcyBtb3N0IHNlbGxpbmcgbWVyY2hhbmRpc2UgZm9yIGFsbCBzcG9uc29ycwoKLSBTaW5jZSwgb25seSBDb2xsZWdlIEdyYWR1YXRlcyBhcmUgbGlrZWx5IHRvIGF0dGVuZCBtYXRjaGVzIG9uIFNhdHVyZGF5IEFmdGVybm9vbnMgMXBtLCBpdCBpcyBpbXBvcnRhbnQgdG8gZmluZCBvdXQgcmVhc29ucyBvZiB3aHkgdGhlIENvbGxlZ2UgYW5kIEdyYWR1YXRlIHN0dWRlbnRzIGFyZSBub3QgYXR0ZW5kaW5nIHRoZSBtYXRjaCwgaXMgdGhlIGRpc3RhbmNlIG9mIHN0YWRpdW0gZmFyIGZyb20gdGhlIGNpdHkgdG8gYXR0ZW5kIHdpdGggZmFtaWx5PyAgICAKCgpTdGF0aXN0aWNhbCBBbmFseXNpcwo9PT09PT09PT09PT09PT09PT09PQoKIzEuIENyb3NzLXRhYiBvZiBCdXlpbmcgcHJlZmVyZW5jZSBhbmQgcHVyY2hhc2Ugc3BvbnNvcnMKCkNoZWNrIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaW4gZWFjaCBDYXRlZ29yeS1SZWdpb24gcGFpciAgCgpgYGB7cn0KIyBOdW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGhlbHBzIHVzIGRldGVybWluZSBpZiBzdGF0cyB3aWxsIGJlIHZhbGlkCnNlYV9yZWlnbl9kYXRhICU+JSAKICB0YWJ5bChtZXJfYnV5X3ByZWYsIG1lcl9wdXJjaGFzZV9zcG9uc29ycykgJT4lIAogIGFkb3JuX3RvdGFscyh3aGVyZSA9IGMoInJvdyIsICJjb2wiKSkKCmBgYAoKTGFyZ2UgZW5vdWdoIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgZm9yIGVhY2ggY2VsbCBpbmRpY2F0ZSBzYW1wbGUgcmVzdWx0cyB3aWxsIGJlIHN0YXRpc3RpY2FsbHkgdmFsaWQgIAoKKyBBc3N1bWluZyB0aGlzIGlzIGEgcmVwcmVzZW50YXRpdmUgc2FtcGxlICAKCiAgICAKIzIuIENoaS1zcXVhcmUgb2YgQnV5aW5nIHByZWZlcmVuY2UgYW5kIHB1cmNoYXNlIHNwb25zb3JzIAoKKyBUZWxsIGlmIHRoZXJlIGlzIGEgcGF0dGVybiBmb3Igd2hpY2ggc3BvbnNvcnMgaGF2ZSBidXlpbmcgcHJlZmVyZW5jZSAgCiAgICAtIEFyZSB0aGUgZmFjdG9yIGxldmVscyBpbmRlcGVuZGVudCAgCgorIE51bGwgaHlwb3RoZXNpczogQXJlIGFsbCBjZWxscyB0aGUgc2FtZSAgCgoKYGBge3J9CiMgQXJlIENhdGVnb3J5IGFuZCBSZWdpb24gc2FsZXMgc2ltaWxhcj8KIyBOb3QgdGlkeXZlcnNlIHNvIGhhdmUgdG8gdXNlIGJhc2UgY29kZQpjaGlzcS50ZXN0KHRhYmxlKHNlYV9yZWlnbl9kYXRhJG1lcl9idXlfcHJlZiwgc2VhX3JlaWduX2RhdGEkbWVyX3B1cmNoYXNlX3Nwb25zb3JzKSkKCmBgYAorIFN0YXRpc3RpY2FsIG1lYXN1cmVzCiAgICAtIHAtdmFsdWU6IFNtYWxsIHAtdmFsdWU7IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzICAKICAgIC0gY2hpLXNxdWFyZTogSGlnaCB2YWx1ZTsgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgIAoKKyBDb25maWRlbmNlIGludGVydmFscyAgCiAgICAtIEJlY2F1c2UgaXMgYSBzYW1wbGUgd2UgY2Fubm90IGJlIHN1cmUgb3VyIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYXJlIHJlcHJlc2VudGF0aXZlIG9mIHRoZSBwb3B1bGF0aW9uICAKICAgIC0gVXNlIENJIG9mIGdpdmVuIGxldmVsIG9mIHNpZ25pZmljYW5jZSB0byBhc3Nlc3MgdGhlIHJlbGlhYmlsaXR5IG9mIHJlc3VsdHMgIAogICAgLSBDSSBhcmUgZ29vZCBmb3IgdmlzdWFsaXphdGlvbiAgCiAgICAKIzMuIFNpZ25pZmljYW5jZSBvZiBjb3JyZWxhdGlvbiAgCgorIE51bGwgaHlwb3RoZXNpczogc2VsZiBhbmQgb3RoZXIgZXhwZW5kaXR1cmUgc29sZCBhcmUgbm90IGNvcnJlbGF0ZWQKCmBgYHtyfQojIEFyZSB0aGUgY29ycmVsYXRpb25zIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQ/CiMgTm90IHRpZHl2ZXJzZSBzbyBoYXZlIHRvIHVzZSBiYXNlIGNvZGUKY29yLnRlc3Qoc2VhX3JlaWduX2RhdGEkc2FsZXNfZXhwX290aDIwMTYsIHNlYV9yZWlnbl9kYXRhJHNhbGVzX2V4cF9zZWxmMjAxNikKCmBgYAoKKyBTdGF0aXN0aWNhbCBtZWFzdXJlcwogICAgLSBwLXZhbHVlOiBzbWFsbCBwLXZhbHVlLCB3ZSByZWplY3QgdGhlIG51bGwgICAKICAgIC0gdC1zdGF0OiBsYXJnZSwgcmVqZWN0IHRoZSBudWxsICAKCiM0LiBUYWJsZSBvZiBwcm9wb3J0aW9ucyB3aXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzICAgCgorIEZhY3RvciB2YXJpYWJsZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzICAKICAgIC0gQ291bnQgLSBkb2VzIG5vdCBnZW5lcmFsaXplIGZyb20gc2FtcGxlIHRvIHBvcHVsYXRpb24gIAogICAgLSBQcm9wb3J0aW9uIC0gaXMgYSBnb29kIGRlc2NyaXB0aXZlIHN0YXQgIAoKCmBgYHtyfQojIFRhYmxlIG9mIGNvdW50cyB0byBjYWxjdWxhdGUgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwKUF9CX24gPC0gc2VhX3JlaWduX2RhdGEgJT4lIAogIGdyb3VwX2J5KG1lcl9idXlfcHJlZiwgbWVyX3B1cmNoYXNlX3Nwb25zb3JzKSAlPiUgCiAgc3VtbWFyaXNlKG4gPSBuKCkpCgojIENhbHVsYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHVzaW5nIG11bGl0bm9taWFsQ0kgICAgICAgICAgIApQX0Jfbl9jaSA8LSBtdWx0aW5vbWlhbENJKHQoUF9CX25bLCAzXSksIDAuMDUpICMgdXNlIHQoKSB0byB0cmFuc3Bvc2UgdGhlIGNvdW50IHRhYmxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBhbHBoYSA9IDAuMDUgaW5kaWNhdGVzIDk1JSBjb25maWRlbmNlIGxldmVsCgojIFRhYmxlIHdpdGggcHJvcG9ydGlvbnMgIApQX0JfdGFibGUgPC0gc2VhX3JlaWduX2RhdGEgJT4lIAogIGdyb3VwX2J5KG1lcl9idXlfcHJlZiwgbWVyX3B1cmNoYXNlX3Nwb25zb3JzKSAlPiUgCiAgc3VtbWFyaXNlKHByb3AgPSBuKCkvc3VtKG5yb3coc2VhX3JlaWduX2RhdGEpKSkKCiMgQWRkIHRoZSBjb25maW5kZW5jZSBpbmVydmFscyB0byB0aGUgdGFibGUgb2YgcHJvcG9ydGlvbnMKUF9CX3RhYmxlJGNpX2wgPC0gUF9CX25fY2lbLDFdClBfQl90YWJsZSRjaV91IDwtIFBfQl9uX2NpWywyXQoKIyBTaG93IHRoZSB0YWJsZQooUF9CX3RhYmxlKQoKYGBgCgoKIzUuIEluY29ycG9yYXRlIENJIGludG8gYmFyIGdyYXBoIG9mIG1lYW5zICAgCgpgYGB7cn0KI0dyYXBoaW5nIG1lYW4gcHJvbW90aW9uYWwgcmV2ZW51ZSBhY3Jvc3MgR2VuZXJhbCBNaWxsIGJyYW5kZWQgY2VyZWFscy4KIyA5MCUgQ0ksIGdldCB6LXZhbHVlIGZvciB1cHBlciB0YWlsLCB1c2UgLjk1IHNpbmNlIGlzIG9uZSBzaWRlZAp6IDwtIHFub3JtKC45NSkKCiMgSW5jb3Jwb3JhdGUgQ0kgaW50byBiYXIgZ3JhcGggb2YgbWVhbnMKc2VhX3N0ICU+JQogIG11dGF0ZShwcm9tbyA9IGlmX2Vsc2UoYXR0X3Byb21vX2VmZmVjdCA9PSAiUG9zaXRpdmUgaW5mbHVlbmNlIiwgIlBvc2l0aXZlIiwgIk5vbmUiKSkgJT4lCiAgbXV0YXRlKHByZWZfdGltZSA9IGNhc2Vfd2hlbihhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIkZyaWRheSBFdmVuaW5ncyIgfiAiRnJpIEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iIH4gIlNhdCBBZnQ0cG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iIH4gIlN1biBBZnQ0cG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIgfiAiU2F0IEFmdDFwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlN1bmRheSBFdmVuaW5ncyIgfiAiU3VuIEV2ZW5pbmdzIikpICU+JQogIGdyb3VwX2J5KHByZWZfdGltZSwgcHJvbW8pICU+JQogIHN1bW1hcmlzZShtID0gbWVhbihzYWxlc19udW1vZm1hdGNoXzIwMTcpLCBzZCA9IHNkKHNhbGVzX251bW9mbWF0Y2hfMjAxNykvNSwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIocHJlZl90aW1lLCBtKSwgeSA9IG0sIGZpbGwgPSByZW9yZGVyKHByb21vLG0pKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbSAtIGNpLCB5bWF4ID0gbSArIGNpKSwgCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArCiAgCiMgIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCIiKSArCiAgbGFicyhmaWxsID0gIlByb21vIEVmZmVjdCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLCBoanVzdCA9IDEpKSArCiAgdGhlbWUoYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMSksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSkgKwogICMgVG8gdXNlIGZvciBmaWxscywgYWRkCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNiUGFsZXR0ZSkgKwogIGdndGl0bGUoIk1lYW4gbnVtYmVyIG9mIFNlYXNvbiBUaWNrZXRzIGxpa2VseSB0byBzZWxsIGluIFNlYXNvbiAyMDE3IiwKICAgICAgICAgIHN1YnRpdGxlID0gIlByb21vcyBhcmUgbm90IGVmZmVjdGl2ZSBvbiB3ZWVrZW5kIG1hdGNoZXMiKQoKYGBgCgorIEludGVycHJldGF0aW9ucyAKIAogICAgMS4gQWxsIHByb3BvcnRpb25zIGFyZSAqKnJlbGlhYmx5KiogZ3JlYXRlciB0aGFuIHplcm8gIAogICAgMi4gU2F0IEFmdGVybm9vbnMgMXBtIHRpY2tldHMgYXJlIGxpa2VseSB0byBzZWxsIG1vc3QgKipwcmFjdGljYWxseSoqIGFuZCAqKnJlbGlhYmx5KiogIAoKKyBDbGVhbmVyIGdyYXBoCgpgYGB7cn0KIyBUaGUgcGFsZXR0ZSB3aXRoIHB1cnBsZXM6CmNiUGFsZXR0ZSA8LSBjKCIjZGRkYWVkIiwiI2M1YjRlMyIsICIjOTU3OGQzIiwgIiM3ZDU1YzciKQoKYmFzZV9wbG90NSA8LSAKc2VhX3N0ICU+JQogIG11dGF0ZShwcm9tbyA9IGlmX2Vsc2UoYXR0X3Byb21vX2VmZmVjdCA9PSAiUG9zaXRpdmUgaW5mbHVlbmNlIiwgIlBvc2l0aXZlIiwgIk5vbmUiKSkgJT4lCiAgbXV0YXRlKHByZWZfdGltZSA9IGNhc2Vfd2hlbihhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIkZyaWRheSBFdmVuaW5ncyIgfiAiRnJpIEV2ZW5pbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dF9tb3N0X3ByZWZfdGltZSA9PSAiU2F0dXJkYXkgQWZ0ZXJub29ucyA0cG0iIH4gIlNhdCBBZnQ0cG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTdW5kYXkgQWZ0ZXJub29ucyA0cG0iIH4gIlN1biBBZnQ0cG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0X21vc3RfcHJlZl90aW1lID09ICJTYXR1cmRheSBBZnRlcm5vb25zIDFwbSIgfiAiU2F0IEFmdDFwbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRfbW9zdF9wcmVmX3RpbWUgPT0gIlN1bmRheSBFdmVuaW5ncyIgfiAiU3VuIEV2ZW5pbmdzIikpICU+JQogIGdyb3VwX2J5KHByZWZfdGltZSwgcHJvbW8pICU+JQogIHN1bW1hcmlzZShtID0gbWVhbihzYWxlc19udW1vZm1hdGNoXzIwMTcpLCBzZCA9IHNkKHNhbGVzX251bW9mbWF0Y2hfMjAxNykvNSwgCiAgICAgICAgICAgIG4gPSBuKCksIGNpID0geiAqIHNkL3NxcnQobikpICU+JQogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIocHJlZl90aW1lLCBtKSwgeSA9IG0sIGZpbGwgPSBwcm9tbykpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKG0sIDEpKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoLjkpLCBzaXplID0gMi41KSArCiMgIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB4bGFiKCIiKSArCiAgeWxhYigiTWVhbiIpICsKICBsYWJzKGZpbGwgPSAiUHJvbW8gRWZmZWN0IikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICB0aGVtZShheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDExKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9Y2JQYWxldHRlKSArCiAgZ2d0aXRsZSgiUHJlZGljdGVkIE1lYW4gbnVtYmVyIG9mIFNlYXNvbiBUaWNrZXRzIGxpa2VseSB0byBzZWxsIGluIFNlYXNvbiAyMDE3IiwKICAgICAgICAgIHN1YnRpdGxlID0gIlByb21vcyBhcmUgc3RhdGlzdGljYWxseSBlZmZlY3RpdmUgb24gU2F0IGFmdGVybm9vbiBvbmx5IikKCmBgYApzZWxlY3QoZmFjdG9yMV9hdHRlbmQsYXR0X2ZpcnN0X2F0dGVuZCxhdHRfaW50ZXJlc3QsYXR0X2dhbWV3aXRoLGF0dF90cmF2ZWxfbW9kZSxhdHRfZGlzdGFuY2UsCiAgICAgICAgIGF0dF9wcm9tb19lZmZlY3QsYXR0X3BsYXllcl9mYW4sYXR0X3NlYUV2ZW50LCBhdHRfbW9zdF9wcmVmX3RpbWUsCiAgICAgICAgIGF0dF9sZWFzdF9wcmVmZXJyZWRfdGltaW5nLGF0dF9hdHRlbmRfMjAxNyxhdHRfYXR0ZW5kXzIwMTYsIGF0dF9nYW1ld2l0aCwKICAgICAgICAgc2FsZXNfdGlja2V0X3R5cGUsIHNhbGVzX2V4cF9zZWxmMjAxNiwgCiAgICAgICAgIHNhbGVzX2V4cF9vdGgyMDE2LHNhbGVzX251bW9mbWF0Y2hfMjAxNyxzYWxlc190a3RfdHlwZV8yMDE3LG1lZGlhX3dlYiwKICAgICAgICAgbWVkaWFfc2Vhc29uX25ld3NwYXBlcixtZWRpYV9zZWFzb25fdHYsCiAgICAgICAgIG1lcl9idXlfcHJlZixjb3N0LAogICAgICAgICBtZXJfcHVyY2hhc2Vfc3BvbnNvcnMsbWVyX3JlaWduLGRlbV9nZW5kZXIsZGVtX3NleHVhbE9yaWVudCxkZW1fbWFyaXRhbF9zdGF0dXMsCiAgICAgICAgIGRlbV9lZHVjYXRpb24sc2F0X2dhbWVkYXksc2F0aXNmYWNuX3BlcmYpICAlPiUKICBkcm9wX25hKCkKCiM2LiBNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbgoKKyBNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBjb250cm9scyBmb3IgYWxsIHZhcmlhYmxlcyBzaW11bHRhbmVvdXNseSAgCiAgICAKYGBge3J9CgojIExpbmVhciByZWdyZXNzaW9uCiMgSW50ZXJhY3Rpb24gdGVybSB1bml0cyBhbmQgcHJvbW8gYmVjYXVzZSBudW1iZXIgb2YgdW5pdHMgYW5kIHByb21vdGlvbnMgY291bGQgYWZmZWN0IHJldmVudWUgKGFwcHJveGltYXRlbHkgMjBwZXJjZW50IGNvcnJlbGF0ZWQpCmJhc2UgPC0gbG0oc2FsZXNfZXhwX3NlbGYyMDE2IH4gc2FsZXNfbnVtb2ZtYXRjaF8yMDE3ICsgc2FsZXNfdGt0X3R5cGVfMjAxNyArIG1lcl9idXlfcHJlZiArIG1lcl9wdXJjaGFzZV9zcG9uc29ycyArIG1lcl9yZWlnbgogICAgICAgICAgICsgZGVtX2VkdWNhdGlvbiwKICAgICAgICAgICAgZGF0YSA9IHNlYV9yZWlnbl9kYXRhKQoKIyBSZXZpZXcgb3V0cHV0CnN1bW1hcnkoYmFzZSkKCmBgYAojIyMgT2JzZXJ2YXRpb25zCiAKKyBSMiBpcyAwLjIzMDEgbWVhbnMgdGhlIG1vZGVsIGNhbiBleHBsYWluIDIzLjAxJSB2YXJpYWJpbGl0eSBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIEV4cGVuZGl0dXJlCisgQ29udHJvbGxpbmcgb3RoZXIgdmFyaWFibGUsIG1lcl9yZWlnbk5vIHByZWZlcmVuY2VzLCBtZXJfcmVpZ25TaG9ydF9TbGVldmVfU2hpcnQgYW5kIAogIG1lcl9wdXJjaGFzZV9zcG9uc29yc1J1ZmZuZWNrIFNjYXJ2ZXMgaGF2ZSBwLXZhbGVzIG9mIDUlIGxldmVsKHA8MC4wMSkuCgoKYGBge3J9CiMgcGxvdCByZXNpZHVhbHMgdG8gY2hlY2sgZm9yIHBhdHRlcm5zCgpwYXIobWZyb3cgPSBjKDEsIDEpKQpwbG90KHNlYV9yZWlnbl9kYXRhJHNhbGVzX2V4cF9zZWxmMjAxNiwgYmFzZSRyZXNpZHVhbHMpCnBsb3Qoc2VhX3JlaWduX2RhdGEkc2FsZXNfbnVtb2ZtYXRjaF8yMDE3LCBiYXNlJHJlc2lkdWFscykKcGxvdChzZWFfcmVpZ25fZGF0YSRhdHRfZGlzdGFuY2UsIGJhc2UkcmVzaWR1YWxzKQoKCmBgYAoKCiM3LlZpc3VhbGl6YXRpb24gb2YgTXVsdGlwbGUgUmVncmVzc2lvbiAKCkhvdyBlYXN5IGlzIGl0IHRvIHVuZGVyc3RhbmQgd2hpY2ggdmFyaWFibGVzIGFyZTogIAoKMS4gTW9zdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50ICAKMi4gSGF2ZSB0aGUgbGFyZ2VzdCBpbXBhY3QgIAoKIyNhLiBUYWJsZSBmb3JtYXQKCmBgYHtyfQojIFB1bGwgb3V0IHRoZSBjb2VmZmljaWVudHMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRhYmxlIGFuZCBncmFwaApjb2UgPC0gc3VtbWFyeShiYXNlKSRjb2VmZmljaWVudHMgIyBnZXQgY29lZmZpY2llbnRzIGFuZCByZWxhdGVkIHN0YXRzCmNvZV9DSSA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGNvZVstMSwgXSwgY29uZmludChiYXNlKVstMSwgXSkpICMgZmluZCBhbmQgYmluZCBDSSwgcmVtb3ZlIEludGVyY2VwdCAKCiMgUmVuYW1lIHJlc3VsdHMgZGF0YSBmcmFtZQpuYW1lcyhjb2VfQ0kpIDwtIGMoImVzdGltYXRlIiwgInNlIiwgInQiLCAicHZhbCIsImxvd19DSSIsImhpZ2hfQ0kiKSAKCmh0bWxUYWJsZShyb3VuZChjb2VfQ0ksMykpCgpgYGAKIyNiLiBUYWJsZTogT3JkZXIgYmFzZWQgb24gcC12YWx1ZQoKYGBge3J9CiMgTWFrZSBhIG5lYXQgdGFibGUKaHRtbFRhYmxlKHJvdW5kKGNvZV9DSVtvcmRlcihjb2VfQ0kkcHZhbCwgZGVjcmVhc2luZyA9IEZBTFNFKSwgXSwgMykpCgpgYGAKCisgVGhlIHAgb2YgMCAgbWVhbnMgdGhhdCB0aGUgcmVzdWx0cyBhcmUgaGlnaGx5IHNpZ25pZmljYW50LCBpdCBzdWdnZXN0cyB0aGVyZSB3YXMgYWJzb2x1dGVseSBubyBvciB6ZXJvIGNoYW5jZSBvZiBnZXR0aW5nIHRoZSByZXN1bHRzIGlmIHRoZSBudWxsIGh5cG90aGVzaXMgd2FzIHRydWUKCiMjYy4gQ2xldmVsYW5kIGRvdCBwbG90ICAKCmBgYHtyfQojIENsZXZlbGFuZCBkb3QgcGxvdCBvZiByZXN1bHRzCmdncGxvdChjb2VfQ0ksIGFlcyh4ID0gZXN0aW1hdGUsIHkgPSByb3cubmFtZXMoY29lX0NJKSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgeGxpbShtaW4oY29lX0NJJGxvd19DSSksIG1heChjb2VfQ0kkaGlnaF9DSSkpICsKICB5bGFiKCJWYXJpYWJsZSIpICsKICB4bGFiKCJDb2VmZmljaWVudCIpICsKICB0aGVtZV9idygpCgpgYGAKICAKCiMjZC4gQ2xldmVsYW5kIGRvdCBwbG90IC0gT3JkZXIgYmFzZWQgb24gcC12YWx1ZQoKVGhpcyB3aWxsIG9yZGVyIGJ5IG1vc3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAgCgpgYGB7cn0KIyBSZW9yZGVyIGZvciBtb3JlIGNsYXJpdHkKKGcxIDwtIGdncGxvdChjb2VfQ0ksIGFlcyh4ID0gZXN0aW1hdGUsIHkgPSByZW9yZGVyKHJvdy5uYW1lcyhjb2VfQ0kpLGRlc2MocHZhbCkpKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICB4bGltKG1pbihjb2VfQ0kkbG93X0NJKSwgbWF4KGNvZV9DSSRoaWdoX0NJKSkgKwogIHlsYWIoIlZhcmlhYmxlIikgKwogIHhsYWIoIkNvZWZmaWNpZW50IikgKwogIHRoZW1lX2J3KCkgCikKIApgYGAKCiAgICAKIzguIEhvdyBhYm91dCBpbmNsdWRlIENJCgorIFZpc3VhbGl6ZSB3aGljaCB2YXJpYWJsZXMgaGF2ZSBjb2VmZmljaWVudHMgc3RhdGlzdGljYWxseSBkaWZmZXJlbnQgZnJvbSB6ZXJvICAKCmBgYHtyfQojIFVzZSBnZW9tX3NlZ21lbnQgdG8gaWxsdXN0cmF0ZSBDSQooZzIgPC0gZzEgKwogIGdlb21fc2VnbWVudChhZXMoeWVuZCA9IHJlb3JkZXIocm93Lm5hbWVzKGNvZV9DSSksZGVzYyhwdmFsKSkpLCAKICAgICAgICAgICAgICAgeGVuZCA9IGNvZV9DSSRoaWdoX0NJLCBjb2xvciA9ICJCbHVlIikgKwogIGdlb21fc2VnbWVudChhZXMoeWVuZCA9IHJlb3JkZXIocm93Lm5hbWVzKGNvZV9DSSksZGVzYyhjb2VfQ0kkcHZhbCkpKSwgCiAgICAgICAgICAgICAgIHhlbmQgPSBjb2VfQ0kkbG93X0NJLCBjb2xvciA9ICJCbHVlIikgKwogICB4bGFiKCJDb2VmZmljaWVudCB3aXRoIENvbmZpZGVuY2UgSW50ZXJ2YWwiKQopCgpgYGAKCisgVmVydGljYWwgbGluZSBhdCAwCisgVm9sdW1lLCBpbnRlcmFjdGlvbiB0ZXJtIGFkTk9ORTp1bml0cywgYWRCOnVuaXRzIGRvIG5vdCBoYXZlIENJIGJhciAKKyBUaGUgcC12YWx1ZSBmb3IgZWFjaCB0ZXJtIHRlc3RzIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgY29lZmZpY2llbnQgaXMgZXF1YWwgdG8gemVybyAobm8gZWZmZWN0KQoKCmBgYHtyfQojIExpbmUgYXQgMCBnaXZlcyBjb250ZXh0CihnMyA8LSBnMiArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIikpCgpgYGAKCgojU3VtbWFyeSBvZiBmaW5kaW5ncwoKKyBJZiBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGluY2x1ZGVzIHRoZSBudWxsIHZhbHVlLCB0aGVuIHRoZXJlIGlzIG5vIHN0YXRpc3RpY2FsbHkgbWVhbmluZ2Z1bCBvciBzdGF0aXN0aWNhbGx5ICAgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBncm91cHMKKyBBbGwgdmFyaWFibGVzIGhhdmUgQ0kgYmFyCisgZGVtX2VkdWNhdGlvbk90aGVyIGhhcyBoaWdoZXN0IENJIGJhciwgbW9yZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50CgoKCgoKCgo=